JPA 在任何查询之前自动刷新

Moh*_*rmi 7 java hibernate jpa flush spring-boot

从 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();
Run Code Online (Sandbox Code Playgroud)

更新:

我注意到刷新只发生在具有 DML 的同一张表上的 JPQL 查询上,而对于本机 sql 查询,如果之前有 DML ,它将始终在任何查询之前刷新。即使没有发生刷新,JPQL 也会返回经过修改的托管实体,而不是数据库中的实体。谁能解释一下这是否符合 JPA 标准吗?

Sim*_*lli 7

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

3.10.8 查询和刷新模式

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

如果持久性上下文尚未加入当前事务,则无论刷新模式设置如何,持久性提供程序都不得刷新到数据库。

package javax.persistence;
public enum FlushModeType {
COMMIT,
AUTO
}
Run Code Online (Sandbox Code Playgroud)

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

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

然后是 Hibernate 文档:

6.1. 自动冲水

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

  • 在提交交易之前

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

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

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