我有一系列JPA持久化和设置者调用(更新)应该在下一行代码执行之前发生,但是记录器显示由持久性产生的hibernate查询发生的时间晚于下一行代码。
myDAO.persist(object1); //insert 1
myOtherDAO.persist(object2); //insert 2
object3.setProperty("value"); //update 1
System.out.println ("*****Message 1");
doWork();
System.out.println("*****Message 2");
Hibernate: insert into tableName1... //insert 1
Hibernate: insert into tableName2... //insert 2
*****Message 1
ERROR BECAUSE UPDATE DIDNT HAPPEN
*****Message 2
Hibernate: update table3 ... //update 1 (too late)
因此,在下一行代码之前,而不是插入1,插入2和更新1,似乎更新1实际上发生得太晚了。有人可以告诉我为什么这发生在我身上以及我做了什么值得吗?
我应该提到这是在集成测试方法中,而doWork()实际上是一个发送到servlet的模拟请求。 servlet是问题发生的地方,因为它没有在数据库中找到预期的状态。 servlet是否在事务之外并且有效地“绕过”休眠状态?我应该在将请求发送到servlet之前刷新吗?
答案 0 :(得分:3)
这是正常和预期的行为。如果每次修改持久属性时Hibernate都会执行更新查询,那么性能将是灾难性的。所有修改实体的状态在刷新时保留在数据库中。冲洗发生
session.flush()
或entityManager.flush()
时因此,您应该没有任何错误,除非您使用JDBC或某些本机查询“在Hibernate后面”进行查询。如果是这样,请在执行此查询之前明确刷新。
答案 1 :(得分:1)
使用ORM时,您需要牢记您的交易。 ORM在事务的范围内工作,并且在1)tx完成时,通常会持续更改DB,2)它命中某种内部标记,或3)当特别指示刷新到DB时, JB Nizet指出。
如果您的代码依赖于给定对象的特定DB状态,例如,代码的另一部分将返回到DB以获取数据,并且该部分代码依赖于该对象处于某种状态,您可能需要回到您的代码并重新思考它是如何编写的。调用可能需要在不同的事务中,或者ORM层中的对象可能具有尚未在实体中设置的关系(如OneToMany
)。
一般来说,你真的不需要做手册flushes
;在刷新数据库时,ORM通常非常有能力保持依赖关系。事实上,根据我自己的经验,我发现通过正确的实体设置,我在编写批处理时只编写了手册flushes
,根据Hibernate手册。