Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当我使用JPA PERSISTER时,为什么我的hibernate查询发生得比预期晚?_Hibernate_Jpa_Persistence - Fatal编程技术网

当我使用JPA PERSISTER时,为什么我的hibernate查询发生得比预期晚?

当我使用JPA PERSISTER时,为什么我的hibernate查询发生得比预期晚?,hibernate,jpa,persistence,Hibernate,Jpa,Persistence,我有一系列JPA持久化和setter调用(更新),这些调用应该在执行下一行代码之前发生,但记录器显示持久化导致的hibernate查询发生的时间晚于下一行代码 代码 记录器显示的内容 因此,与insert 1、insert 2和update 1都发生在下一行代码之前不同,update 1实际上发生得太晚了。有人能告诉我为什么这件事会发生在我身上,我做了什么,这是我应得的吗 编辑 我应该提到,这是在一个集成测试方法中,而doWork()实际上是一个发送到servlet的模拟请求。servlet是出

我有一系列JPA持久化和setter调用(更新),这些调用应该在执行下一行代码之前发生,但记录器显示持久化导致的hibernate查询发生的时间晚于下一行代码

代码 记录器显示的内容 因此,与insert 1、insert 2和update 1都发生在下一行代码之前不同,update 1实际上发生得太晚了。有人能告诉我为什么这件事会发生在我身上,我做了什么,这是我应得的吗

编辑
我应该提到,这是在一个集成测试方法中,而doWork()实际上是一个发送到servlet的模拟请求。servlet是出现问题的地方,因为它在数据库中找不到预期的状态。servlet是否在事务之外并且有效地“绕过”了hibernate?我应该在向servlet发送请求之前刷新吗?

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

  • 在提交时
  • 当您明确地调用
    session.flush()或
    entityManager.flush()时
  • 执行查询已修改实体的一个表的查询(HQL或条件)时

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

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

  • 在提交时
  • 当您明确地调用
    session.flush()或
    entityManager.flush()时
  • 执行查询已修改实体的一个表的查询(HQL或条件)时

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

使用ORMs时,需要记住事务。ORM在事务范围内工作,通常在1)发送完成时,2)到达某种内部标记时,或3)如JB Nizet所述,当特别指示刷新到DB时,ORM将保留对DB的更改

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


不过,一般来说,您确实不需要手动刷新
;在刷新数据库时,ORM通常非常善于记住依赖关系。事实上,根据我自己的经验,我发现在正确的实体设置下,我在进行批处理编码时,只按照Hibernate手册对手动
刷新进行了编码。

在使用ORM时,您需要记住您的事务。ORM在事务范围内工作,通常在1)发送完成时,2)到达某种内部标记时,或3)如JB Nizet所述,当特别指示刷新到DB时,ORM将保留对DB的更改

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


不过,一般来说,您确实不需要手动刷新
;在刷新数据库时,ORM通常非常善于记住依赖关系。事实上,根据我自己的经验,我发现通过正确的实体设置,我在进行批处理编码时,只按照Hibernate手册编写了手动
刷新代码。

即使是JPQL查询也可以“绕过缓存”。@jbnizet感谢您的回复,请看我的更新,并提供任何进一步的反馈。然后你有一个更大的理解问题。事务彼此独立运行。这是事务的核心原则之一(ACID中的I)。因此,默认情况下(隔离模式设置为read_committed),servlet事务不会看到测试事务内部所做的更改,因为它还没有提交。阅读并@JBNizet是的,这是一个很大的理解问题,因为我不熟悉ORMs、集成测试和JEE。不过,这是一些很好的见解,我从您提供的链接中学到了很多。当从测试事务调用servlet时,是否习惯于在发送模拟请求之前刷新/提交事务?您必须提交它,否则servlet将看不到任何内容。冲洗不够。刷新只会将Hibernate缓存中的更改写入数据库,但不会提交。即使是JPQL查询也可以“绕过缓存”。@jbnize谢谢您的回复,请查看我的更新并提供任何进一步的反馈。然后您会遇到更大的理解问题。事务彼此独立运行。这是事务的核心原则之一(ACID中的I)。因此,默认情况下(隔离模式设置为read_committed
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)