当我使用JPA持久化时,为什么我的hibernate查询发生的时间比预期要晚?

时间:2012-03-16 21:02:57

标签: hibernate jpa persistence

我有一系列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之前刷新吗?

2 个答案:

答案 0 :(得分:3)

这是正常和预期的行为。如果每次修改持久属性时Hibernate都会执行更新查询,那么性能将是灾难性的。所有修改实体的状态在刷新时保留在数据库中。冲洗发生

  • 在提交时
  • 当您明确地致电session.flush()entityManager.flush()
  • 执行查询(HQL或Criteria)时查询已修改实体的其中一个表

因此,您应该没有任何错误,除非您使用JDBC或某些本机查询“在Hibernate后面”进行查询。如果是这样,请在执行此查询之前明确刷新。

答案 1 :(得分:1)

使用ORM时,您需要牢记您的交易。 ORM在事务的范围内工作,并且在1)tx完成时,通常会持续更改DB,2)它命中某种内部标记,或3)当特别指示刷新到DB时, JB Nizet指出。

如果您的代码依赖于给定对象的特定DB状态,例如,代码的另一部分将返回到DB以获取数据,并且该部分代码依赖于该对象处于某种状态,您可能需要回到您的代码并重新思考它是如何编写的。调用可能需要在不同的事务中,或者ORM层中的对象可能具有尚未在实体中设置的关系(如OneToMany)。

一般来说,你真的不需要做手册flushes;在刷新数据库时,ORM通常非常有能力保持依赖关系。事实上,根据我自己的经验,我发现通过正确的实体设置,我在编写批处理时只编写了手册flushes,根据Hibernate手册。