我使用此代码制作实体的副本:
EntityClass obj = em.find(...);
em.detach(obj);
obj.setId(null);
obj.setName("New");
em.persist(obj);
em.flush();
所以问题是 - 如果我从这个创建的副本中创建一个新副本,它们都指向实体管理器缓存中最后创建的副本!
// Call#1 copy method
Entity obj = em.find(Entity.class, 1); // old object, id = 1
em.detach(obj);
obj.setId(null);
em.persist(obj); // created new object with id = 2
em.flush();
// Call#2 copy method
Entity obj2 = em.find(Entity.class, 2); // our copy, id = 2
em.detach(obj2);
obj2.setId(null);
em.persist(obj2); // created new object with id = 3
em.flush();
// Call another method
Entity someObj = em.find(Entity.class, 2); // returns last copy with id=3!
// it's like after persist obj2 (id=2) points
// to the same memory address as the new copy with id = 3
复制方法执行后的evictAll()使其颠倒 - 现在id = 2和id = 3都指向id = 2的原始副本。
我认为这与某种事实相关,即在Java中我们不使用构造函数创建新对象,并且变量保持不变,而在数据库中存在两个实体。
答案 0 :(得分:1)
问题的根源是你和JPA之间的主要冲突:
因此,不是使用JPA,而是在与它作斗争。
如果你试着追随这件衣服,你会得到一些脆弱和丑陋的东西 - 而且你也会觉得JPA在某种程度上让你失望(当你试图用螺丝刀锤击钉子时会有同样的感觉)。< / p>
要使其顺利运作,您需要做的是:
您最终可能会得到优雅,可测试的代码,这些代码没有显式的缓存操作,没有刷新,没有“合并”,也没有“分离”。
抱歉,我知道这不是您想听到的建议类型。如果你想进入JPA思维模式并看到JPA行为的基本原理,请查看经典的Fowler企业模式,特别是工作单元和身份地图