Я использую JPA с поставщиком гибернации. Heres моя часть кода:JPA merge() на отдельном объекте делает вставку, когда она существует
@Entity
@IdClass(xxxPK.class)
@NamedQueries({
...
})
@Inheritance(strategy = InheritanceType.JOINED)
public class xxx extends AbstractEntity {
public static final String GET_TRADES = "getInstruments";
public static final String GET_STRUCTURE = "getStructure";
public static final String GET_ALL = "getAllTrades";
@Column(nullable = false)
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "xxx")
@SequenceGenerator(name = "xxxx", sequenceName = "xxxxS", allocationSize = 1)
private Long systemId;
@Id
@Column(nullable = false)
private Integer version;
//////
И потомок:
@Entity
@PrimaryKeyJoinColumns(
{
@PrimaryKeyJoinColumn(name = "systemId"),
@PrimaryKeyJoinColumn(name = "version")
}
)
public class YYY extends xxx {
//////
Я создаю экземпляр YYY и persiti как я ожидал. После этого я на одну строку в каждой таблице в дБ:
fx = Persistence.invoke(new Persistence.Invoke<YYY>() {
@Override
public YYY run(EntityManager em) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(new ClassPathResource("json/XXX_from.json").getFile()));
} catch (IOException ex) {
System.out.print("File is not found");
}
YYYfx = (YYY) EntityConverter.getConverter(YYY.class).fromJson(reader);
em.persist(fx);
return fx;
}
});
Таким образом, после того, что FX отсоединяется и, как SPEC. саис я могу сделать его постоянным в другой сессии, вызвав слияния(), так называю его, но:
Persistence.invoke(new Persistence.Invoke<Object>() {
@Override
public Object run(EntityManager em) {
fx.setZZZ("A");
em.merge(fx);
return null;
}
});
После этого я иметь другую строку в XXX и YYY таблицах с новым первичным. Похоже, что провайдер принимает fx как TRANSIENT, а не DETACHED, тогда он sais ok - это новый объект, и я бы его вставлял. Я не знаю, что делать, я потерял 4 часа в таком глупом случае. Пожалуйста помоги!
public class Persistence {
private static EntityManagerFactory emf;
public static EntityManagerFactory getEmf() {
return emf;
}
public void setEmf(EntityManagerFactory emf) {
Persistence.emf = emf;
}
public static <T> T invoke(Invoke<T> inv) {
T result = null;
EntityManager em = getEmf().createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
try {
result = inv.run(em);
transaction.commit();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
em.close();
}
return result;
}
public interface Invoke<T> {
public T run(EntityManager em);
}
}