improve discussion of FlushModes and CacheModes

This commit is contained in:
Gavin 2023-05-13 18:59:35 +02:00 committed by Gavin King
parent 99ba5cba1e
commit f424a4b2f2
2 changed files with 54 additions and 3 deletions

View File

@ -357,6 +357,25 @@ s.setHibernateFlushMode(FlushMode.MANUAL);
Since flushing is a somewhat expensive operation (the session must dirty-check every entity in the persistence context), setting the flush mode to `COMMIT` can occasionally be a useful optimization.
.Flush modes
[cols=",,3"]
|===
| Hibernate `FlushMode` | JPA `FlushModeType` | Interpretation
| `MANUAL` | | Never flush automatically
| `COMMIT` | `COMMIT` | Flush before transaction commit
| `AUTO` | `AUTO` | Flush before transaction commit, and before execution of a query whose results might be affected by modifications held in memory
| `ALWAYS` | | Flush before transaction commit, and before execution of every query
|===
A second way to reduce the cost of flushing is to load entities in _read-only_ mode:
- `Session.setDefaultReadOnly(false)` specifies that all entities loaded by a given session should be loaded in read-only mode by default,
- `SelectionQuery.setReadOnly(false)` specifies that every entity returned by a given query should be loaded in read-only mode, and
- `Session.setReadOnly(Object, false)` specifies that a given entity already loaded by the session should be switched to read-only mode.
It's not necessary to dirty-check on entity instance in read-only mode.
[[queries]]
=== Queries

View File

@ -319,7 +319,7 @@ You can find much more information about the second-level cache in the
For the most part, the second-level cache is transparent.
Program logic which interacts with the Hibernate session is unaware of the cache, and is not impacted by changes to caching policies.
At worst, interaction with the cache may be controlled by specification of an explicit `CacheMode`.
At worst, interaction with the cache may be controlled by specifying of an explicit `CacheMode`:
[source,java]
----
@ -336,7 +336,7 @@ em.setCacheStoreMode(CacheStoreMode.BYPASS);
The JPA-defined cache modes are:
.Cache modes
.JPA-defined cache modes
[cols=",3"]
|===
| Mode | Interpretation
@ -349,16 +349,48 @@ The JPA-defined cache modes are:
| `CacheStoreMode.BYPASS` | Don't write data to the cache
|===
A Hibernate `CacheMode` packages a `CacheRetrieveMode` with a `CacheStoreMode`.
.Hibernate cache modes and JPA equivalents
[cols=",5"]
|===
| `CacheMode` | Equivalent JPA modes
| `NORMAL` | `CacheRetrieveMode.USE`, `CacheStoreMode.USE`
| `IGNORE` | `CacheRetrieveMode.BYPASS`, `CacheStoreMode.BYPASS`
| `GET` | `CacheRetrieveMode.USE`, `CacheStoreMode.BYPASS`
| `PUT` | `CacheRetrieveMode.BYPASS`, `CacheStoreMode.USE`
| `REFRESH` | `CacheRetrieveMode.REFRESH`, `CacheStoreMode.BYPASS`
|===
There's no particular reason to prefer Hibernate's `CacheMode` to the JPA equivalents.
This enumeration only exists because Hibernate had cache modes long before they were added to JPA.
[TIP]
// .A good time to `BYPASS` the cache
====
It's a good idea to set the `CacheStoreMode` to `BYPASS` just before running a query which returns a large result set full of data that we don't expect to need again soon.
This saves work, and prevents the newly-read data from pushing out the previously cached data.
In JPA we would use this idiom:
[source,java]
----
em.setCacheStoreMode(CacheStoreMode.BYPASS);
List<Publisher> allpubs = em.createQuery("from Publisher", Publisher.class).getResultList();
List<Publisher> allpubs =
em.createQuery("from Publisher", Publisher.class)
.getResultList();
em.setCacheStoreMode(CacheStoreMode.USE);
----
But Hibernate has a better way:
[source,java]
----
List<Publisher> allpubs =
s.createSelectionQuery("from Publisher", Publisher.class)
.setCacheStoreMode(CacheStoreMode.BYPASS)
.getResultList();
----
====