我正在使用 JPA 的 Hibernate 实现。假设我有一个对象列表,必须将其保留在名为“事件”的表中。所有这些对象都具有相同的邮政编码。
public class Event {
String id;
String zipCode;
String locationCode;
String eventName;
String eventDesc;
}
此处,id
是主键,zipCode
和 locationCode
一起构成唯一键 (UK_zipCode_locationCode)。该表可能已经包含具有给定邮政编码的对象。因此,我所做的不是查找应该添加、删除或更新哪些对象,而是先删除表中具有给定邮政编码的所有对象,然后插入所有给定对象。
// getEventsToAdd method returns the list of events to be added for the zipCode 1234
// getEventsFromTheDB method returns all the events in the db with the zipCode 1234
List<Event> eventsToAdd = getEventsToAdd("1234");
List<Event> oldEvents = getEventsFromTheDB("1234");
for (Event e : oldEvents) {
entityManager.remove(e);
}
for (Event e : eventsToAdd) {
entityManager.persist(e);
}
entityManager.flush();
// ...
当 oldEvents
列表为空或者 oldEvents
中的所有对象也在 eventsToAdd
列表中时(我的意思是具有相同 id 和相同邮政编码的事件对象)。
但是,如果 oldEvents
中有一些事件对象具有不同的 id,即与 eventsToAdd
列表中任何对象的 id 不匹配,则会抛出异常异常(exception)
Duplicate Entry found for key UK_zipCode_locationCode
错误就好像旧事件没有从表中删除,现在插入具有相同 zipCode 和 locationCode 值的事件会导致 org.hibernate.exception.ConstraintViolationException
。
但是,如果我在删除旧事件后调用 entityManager.flush()
,它就会起作用 -
// This works!
for (Event e : oldEvents) {
entityManager.remove(customizedProviderAttribute);
}
// flush after removing all the old events
entityManager.flush();
for (Event e : eventsToAdd) {
entityManager.persist(e);
}
那么,为什么最后刷新不起作用,但删除旧实体后刷新却起作用?
最佳答案
默认情况下,EntityManager 在提交事务时执行所有 SQL 命令。但是,它可以决定执行 SQL 命令的顺序,在您的情况下,插入是在删除之前完成的,这会导致 ConstraintViolationException
。 flush()
使所有 SQL 立即执行,因此您可以实现先删除后插入。世界并不完美,Hibernate 也不是完美的。
关于java - EntityManager.remove 和 EntityManager.persist 上的 JPA 重复条目错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72057841/