public void whyEntityExistsExceptionisnotthrown(){
EntityManager em=getEntityManager();
try{
Partner partnerOne=em.find(Partner.class, 1L); // from the database
System.out.println("Partner partnerOne information-----------> "+partnerOne.getName());
Partner partnerTwo =new Partner();
partnerTwo.setIdpartner(1L);
partnerTwo.setName("Partner 200");
em.persist(partnerTwo);
Partner partnerThree=em.find(Partner.class, 1L);
// the method find has two entities with the id 1L. I think this could be a problem.
if(em.contains(partnerOne))
System.out.println("PartnerOne managed");
if(em.contains(partnerTwo))
System.out.println("PartnerTwo managed");
System.out.println("Partner partnerTwo information-----------> "+partnerTwo.getName());
System.out.println("Partner partnerThree information-----------> "+partnerThree.getName());
}catch(EntityExistsException e){
System.out.println("The entity already exist");
}
}
通过这篇文章,我试图通过允许两个实体在持久化上下文中具有相同的id来发现问题。 问题是: 有没有办法避免在调用flush方法或提交之前在持久化上下文中有两个具有相同id的托管实体? 为什么不抛出异常?
如果我调用此方法,结果是:
首先调用whyEntityExistsExceptionisnotthrown partnerOne:来自数据库的信息(我在id = 1的数据库中有一个合作伙伴) partnerTwo:Name = Partner 200 partnerThree:Name = Partner 200(但可能是partnerOne的信息。
下一个电话 partnerOne ------>名称=合作伙伴200 partnerTwo ------>名称=合作伙伴200 partnerThree ---->名称=合作伙伴200
答案 0 :(得分:0)
根据persist()方法的文档,它会抛出
EntityExistsException - 如果实体已存在。 (如果是实体 已存在,可能会抛出EntityExistsException 调用persist操作,或EntityExistsException 或其他 在刷新或提交时可能会抛出PersistenceException 。)
因此,为了确保您的persist()
到达数据库,您应该在保留实体后立即调用em.flush()
,然后您将获得一个异常(调用{时出现EntityExistsException) {1}}或EntityExistsException / PersistenceException persist
)。是的,有人可能会问自己为什么JPA规范在这一点上不是很清楚,但我很确定有充分的理由,比如性能(尝试对DB进行单个I / O操作)。因此,如果您需要可移植/工作代码,请调用flush
操作。您可能不明白,在事务提交之前,大多数操作(例如flush()
,remove
,merge
都无法保证到达DB。因此,您有责任在需要时致电persist
。
回答您的问题:
有没有办法避免可能有两个托管实体 在调用flush方法之前,持久化上下文中的相同id 还是提交?
我对此表示怀疑,而且到目前为止我还没有发现需要(!调用flush!)。据我所知,JPA规范。不需要。
为什么不抛出异常?
因为在那一刻不能保证flush()
与DB同步。文档说得很清楚。
一些重要说明:
据我所知,您的ID字段不会自动生成。通常,应用程序允许DB生成ID,以便调用persist
与DB同步。
此外,在您的代码中(未经测试)我确信persist
被评估为true,这意味着它们实际上是完全相同的对象。唯一的问题是partnerOne==partnerThree
,你必须冲洗。