【问题标题】:JPA auto flush before any queryJPA 在任何查询之前自动刷新
【发布时间】:2019-11-10 17:25:35
【问题描述】:

从 JPA 文档中我可以看到 AUTO 是默认的刷新模式,刷新应该在任何查询执行之前发生。我在spring boot jpa上试过这个,我可以看到来自不同实体的查询不会发生刷新,这是预期的吗?即使不同的实体可能与它有关系(部门 这里的人)

根据本文,刷新应该在任何查询之前触发: https://vladmihalcea.com/how-do-jpa-and-hibernate-define-the-auto-flush-mode/

// this triggers flush //
 Person person = personRepository.findById(5L).get();
 person.setName("hello test");
 Person person1 = (Person) entityManager.createQuery("select person from Person 
 person where person.id=11").getSingleResult(); // flush before query



// this doesn't trigger flush even if  the department has the person //
 Person person = personRepository.findById(5L).get();
 person.setName("hello test");
 Department department= (Department) entityManager.createQuery("select 
 department from Department
department where department.id=1").getSingleResult();

更新:

我注意到刷新发生在仅具有 DML 的同一个表上的 JPQL 查询中,而对于本机 sql 查询,如果之前有 DML,它将始终在任何查询之前刷新。即使没有发生刷新,JPQL 也会返回带有修改的托管实体,而不是 DB 中的那个。谁能解释一下这是否遵循 JPA 标准?

【问题讨论】:

  • 阅读这里,没有比 Vlad 更好的来源了:vladmihalcea.com/…
  • @Shadov 我读过,但它与 hibernate 相关,我使用的是 jpa 而没有本机查询
  • @MohammadKarmi JPA 只是一个规范/文档。 Hibernate EclipseLink 等是它的实现。您正在使用休眠或其他提供程序。
  • @AlexandarPetrov 我知道,但是 JPA 以不同的方式进行刷新vladmihalcea.com/…
  • @MohammadKarmi 今天我学到了一些新东西 :)

标签: java hibernate spring-boot jpa flush


【解决方案1】:

由于 JPA 是一个规范,这个问题很容易回答。查看规范:-)

3.10.8 查询和刷新模式

刷新模式设置对查询结果的影响如下。 在事务中执行查询时,如果在 Query、TypedQuery 或 StoredProcedureQuery 对象上设置了 FlushModeType.AUTO,或者持久性上下文的刷新模式设置为 AUTO(默认值)并且尚未为查询对象,持久化提供者负责确保对持久化上下文中所有实体状态的所有更新,这些更新可能会影响查询的结果,对查询的处理是可见的。 询问。持久性提供者实现可以通过将这些实体刷新到数据库或通过其他方式来实现这一点。如果设置了 FlushModeType.COMMIT,则未指定对持久性上下文中的实体进行的更新对查询的影响。

如果持久化上下文没有加入到当前事务中,持久化提供者必须 无论刷新模式设置如何,都不会刷新到数据库。

package javax.persistence;
public enum FlushModeType {
COMMIT,
AUTO
}

如果没有事务处于活动状态,则持久性提供程序不得刷新到数据库

https://download.oracle.com/otn-pub/jcp/persistence-2_1-fr-eval-spec/JavaPersistence.pdf?AuthParam=1561799350_4cc62583442da694a6a033af82faf986

然后是 Hibernate Doc:

6.1。自动冲洗

默认情况下,Hibernate 使用自动刷新模式,在以下情况下触发刷新:

  • 提交事务之前

  • 在执行与排队实体操作重叠的 JPQL/HQL 查询之前

  • 在执行任何未注册同步的本机 SQL 查询之前

https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#flushing

【讨论】:

  • 你的意思是hibernate遵循JPA规范是因为“持久性提供程序实现可以通过将这些实体刷新到数据库或通过其他方式来实现这一点。”通过其他方式不需要刷新只需实现查询的可见性?
  • 是的,当然。我添加了休眠文档的部分
  • 谢谢,这非常有用,最后一个问题,在我的情况下,部门与人有关系,为什么没有触发冲洗?没有重叠吗?
  • 查询部门时,人有变化吗?
  • 是的,我之前确实设置了名称。您可以比较上面的 2 个案例,这看起来很奇怪,为什么部门不需要 flush , Person 是它的孩子。
猜你喜欢
  • 1970-01-01
  • 2018-06-21
  • 2011-05-23
  • 2011-07-07
  • 2012-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多