我正在使用JPA(Hibernate作为JPA提供程序)。我有一个删除实体的操作,似乎如果我分离实体并立即合并它就会抛出异常,即
em.find(entity.class, entitiy.getId())
em.detach(entity)
em.merge(entity)
只需就会导致错误
em.find(entity.class, entitiy.getId())
完美无瑕。关于分离和合并,我有什么遗漏吗?我没有对实体本身做任何事情,它没有改变,所以合并不应该改变任何东西。
如果需要,我可以详细说明我的具体案例。
修改
正如@rmertins指出的那样,我应该使用合并中的返回值,因为merge返回合并实体,而我们用作参数的实体保持分离。这有效:
em.find(entity.class, entitiy.getId())
em.detach(entity)
entity = em.merge(entity)
答案 0 :(得分:2)
是否仍然使用旧的实体引用而不是合并返回的引用?
The merge operation doesn't reattach the given entity。合并操作查找已经加载的实体,因为它找不到(因为你将它分离),它从数据库加载实体,并将提供的实体数据复制到数据库中的新副本。
如果您这样做:
MyEntity myEntity = em.find(MyEntity.class, myEntity.getId())
em.detach(myEntity);
em.merge(myEntity);
然后您只是丢弃实际的合并实体,因为您没有将myEntity重新分配给合并结果。你应该这样做:
myEntity = em.merge(myEntity);
现在myEntity将引用一个附加实体(在第一级缓存a.k.a持久化上下文中加载的实体)。
答案 1 :(得分:1)
对不起我的错,快点。
看这里,非常好的解释:
http://blog.xebia.com/2009/03/23/jpa-implementation-patterns-saving-detached-entities/
这是重要的句子:
这意味着在调用EntityManager.merge之后,我们必须使用 从该方法返回的实体引用代替原始引用 对象传入。
所以线索是合并后你的实体对象仍然是分离的,但是从merge中得到的对象副本再次附加到持久化上下文。