Bypass managed entities or not on JPA
为什么
JPA规范似乎没有规定这样做。是否只是为了在出现不一致风险的情况下获得更好的性能?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* ... */ String name = em.find(Person.class, 1).getName(); em.getTransaction().begin(); em.createQuery("update Person set name='new' where id=1") .executeUpdate(); em.getTransaction().commit(); // DB updated but the entity not Person p = em .createQuery("select p from Person p where id=1", Person.class) .getSingleResult(); // the stale entity returned assertEqual(name, p.getName()); // true |
可能出于性能原因,如果JPQL查询与内存中已加载到实体管理器中的任何实体匹配,则规范不需要使用DB中的当前状态刷新内存中的实体。
在您的示例中,这就是后台发生的情况
-从数据库检索ID为1的人员实体(现在存在于EntityManager缓存中)
-人名通过JPQL在数据库中更新(实体保持不变)
-从数据库中检索ID为1的实体人
-但ID为1的实体已存在于EntityManager中,因此将返回此实例(名称中具有旧值)-该实体未与DB合并。有关更多信息,请参见此问题的答案。
此行为符合JPA要求,即在单个EntityManager中,DB中的单个行不能有2个实体实例。解决问题的方法只有两种,一种是将现有实体与数据库中的状态合并,另一种是忽略数据库中的数据。 JPA规范选择了第二个选项。
如果您一开始不检索ID为1的Person,它将在select查询中检索具有新值的新实体。
在实体中拥有新数据的一种解决方案是在
但是,更安全的解决方案是在使用更新脚本更改实体后使用