JPA AUTO刷新模式疑问:跨实体查询未触发刷新是否合规?
Great question—let's break this down step by step, since JPA's AUTO flush mode can feel counterintuitive at first glance. To cut to the chase: all your observations are completely aligned with JPA standards and Hibernate's (Spring Boot JPA's default provider) implementation of the AUTO flush mode. Here's why each test case behaves the way it does:
1. Why cross-entity queries don't trigger a flush
The JPA spec defines AUTO as the default flush mode, where the provider gets to decide when to sync the persistence context with the database. For Hibernate, AUTO only triggers a flush when the query you're running references tables that have pending dirty changes in the context.
Take your second test case:
Person person = personRepository.findById(5L).get(); person.setName("hello test"); // Dirty change to the Person table Department department= (Department) entityManager.createQuery("select department from Department department where department.id=1").getSingleResult();
Your JPQL query targets the Department table, not the Person table where you made changes. Even though the two entities are associated, Hibernate doesn't see this query as needing a flush—since it doesn't touch the modified Person table. This is expected behavior.
2. Why same-table JPQL queries trigger a flush
In your first test case:
Person person = personRepository.findById(5L).get(); person.setName("hello test"); // Dirty change to the Person table Person person1 = (Person) entityManager.createQuery("select person from Person person where person.id=11").getSingleResult();
Your JPQL query directly references the Person table, which has pending changes. Hibernate flushes the context first to ensure the query returns consistent data (matching the latest state you've modified in memory). This is exactly how AUTO is designed to work for entity-specific queries.
3. Why native SQL queries always trigger a flush
Hibernate can't parse the table dependencies of native SQL queries—it has no way to know if your native query references tables with pending changes. To avoid returning stale data, Hibernate errs on the side of caution and always flushes the persistence context before executing any native SQL query. This is a deliberate choice that aligns with JPA's goal of data consistency, even if it's more aggressive than JPQL handling.
4. Why JPQL returns modified managed entities (even without a flush)
When you run a JPQL query, Hibernate first checks the persistence context (first-level cache) for matching entities. If the entity is already managed (like your Person with ID 5L), it returns the in-memory, modified version directly—no trip to the database needed. This is a core JPA feature: the persistence context keeps track of all managed entities to ensure you work with a consistent view of their state, regardless of whether changes have been flushed to the database yet. This is fully compliant with the JPA standard.
内容的提问来源于stack exchange,提问作者Mohammad Karmi

