问题
From JPA documentation I can see that the AUTO is the default flush mode, flush should happen before any query execution. I have tried this on spring boot jpa and I can see the flush won't happen on queries from different entities , is that expected ? even though different entity may have relation to it ( Department <--> Person here )
The flush should trigger before any query according to this article : 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();
Update:
I noticed the flush happens for JPQL queries on the same table only that has the DML , while for native sql queries it will always flush before any query if there is DML before. even though no flush happens the JPQL return the managed entity with modification not the one in DB. can anyone please explain if this follow JPA standard or not ?
回答1:
As JPA is a specification this question is simple to answer. Check out the spec :-)
3.10.8 Queries and Flush Mode
The flush mode setting affects the result of a query as follows. When queries are executed within a transaction, if FlushModeType.AUTO is set on the Query, TypedQuery, or StoredProcedureQuery object, or if the flush mode setting for the persistence context is AUTO (the default) and a flush mode setting has not been specified for the query object, the persistence provider is responsible for ensuring that all updates to the state of all entities in the persistence context which could potentially affect the result of the query are visible to the processing of the query. The persistence provider implementation may achieve this by flushing those entities to the database or by some other means. If FlushModeType.COMMIT is set, the effect of updates made to entities in the persistence context upon queries is unspecified.
If the persistence context has not been joined to the current transaction, the persistence provider must not flush to the database regardless of the flush mode setting.
package javax.persistence;
public enum FlushModeType {
COMMIT,
AUTO
}
If there is no transaction active, the persistence provider must not flush to the database
https://download.oracle.com/otn-pub/jcp/persistence-2_1-fr-eval-spec/JavaPersistence.pdf?AuthParam=1561799350_4cc62583442da694a6a033af82faf986
Then there is the Hibernate Doc:
6.1. AUTO flush
By default, Hibernate uses the AUTO flush mode which triggers a flush in the following circumstances:
prior to committing a Transaction
prior to executing a JPQL/HQL query that overlaps with the queued entity actions
before executing any native SQL query that has no registered synchronization
https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#flushing
来源:https://stackoverflow.com/questions/56812221/jpa-auto-flush-before-any-query