HHH-12155 - Update documentation regarding limitation of defining caching on just root entity
This commit is contained in:
parent
c4067f611c
commit
da8e13c453
|
@ -132,50 +132,31 @@ include::
|
||||||
[[caching-mappings-inheritance]]
|
[[caching-mappings-inheritance]]
|
||||||
=== Entity inheritance and second-level cache mapping
|
=== Entity inheritance and second-level cache mapping
|
||||||
|
|
||||||
When using inheritance, the JPA `@Cacheable` and the Hibernate-specific `@Cache` annotations should be declared at the root-entity level only.
|
Traditionally, when using entity inheritance, Hibernate required an entity hierarchy to be either cached entirely or not cached at all.
|
||||||
That being said, it is not possible to customize the base class `@Cacheable` or `@Cache` definition in subclasses.
|
Therefore, if you wanted to cache a subclass belonging to a given entity hierarchy,
|
||||||
|
the JPA `@Cacheable` and the Hibernate-specific `@Cache` annotations would have to be declared at the root-entity level only.
|
||||||
|
|
||||||
Although the JPA 2.1 specification says that the `@Cacheable` annotation could be overwritten by a subclass:
|
Although we still believe that all entities belonging to a given entity hierarchy should share the same caching semantics,
|
||||||
|
the JPA specification says that the `@Cacheable` annotation could be overwritten by a subclass:
|
||||||
|
|
||||||
[quote, Section 11.1.7 of the JPA 2.1 Specification]
|
[quote, Section 11.1.7 of the JPA 2.1 Specification]
|
||||||
____
|
____
|
||||||
The value of the `Cacheable` annotation is inherited by subclasses; it can be
|
The value of the `Cacheable` annotation is inherited by subclasses; it can be overridden by specifying `Cacheable` on a subclass.
|
||||||
overridden by specifying `Cacheable` on a subclass.
|
|
||||||
____
|
____
|
||||||
|
|
||||||
Hibernate requires that a given entity hierarchy share the same caching semantics.
|
|
||||||
|
|
||||||
The reasons why Hibernate requires that all entities belonging to an inheritance tree share the same caching definition can be summed as follows:
|
|
||||||
|
|
||||||
- from a performance perspective, adding an additional check on a per entity type level would slow the bootstrap process.
|
|
||||||
- providing different caching semantics for subclasses would violate the https://en.wikipedia.org/wiki/Liskov_substitution_principle[Liskov substitution principle].
|
|
||||||
+
|
|
||||||
Assuming we have a base class, `Payment` and a subclass `CreditCardPayment`.
|
|
||||||
If the `Payment` is not cacheable and the `CreditCardPayment` is cached, what should happen when executing the following code snippet:
|
|
||||||
+
|
|
||||||
[source, JAVA, indent=0]
|
|
||||||
----
|
|
||||||
Payment payment = entityManager.find(Payment.class, creditCardPaymentId);
|
|
||||||
CreditCardPayment creditCardPayment = (CreditCardPayment) CreditCardPayment;
|
|
||||||
----
|
|
||||||
+
|
|
||||||
In this particular case, the second level cache key is formed of the entity class name and the identifier:
|
|
||||||
+
|
|
||||||
[source, JAVA, indent=0]
|
|
||||||
----
|
|
||||||
keyToLoad = {org.hibernate.engine.spi.EntityKey@4712}
|
|
||||||
identifier = {java.lang.Long@4716} "2"
|
|
||||||
persister = {org.hibernate.persister.entity.SingleTableEntityPersister@4629}
|
|
||||||
"SingleTableEntityPersister(org.hibernate.userguide.model.Payment)"
|
|
||||||
----
|
|
||||||
+
|
|
||||||
Should Hibernate load the `CreditCardPayment` from the cache as indicated by the actual entity type, or it should not use the cache since the `Payment` is not supposed to be cached?
|
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
Because of all these intricacies, Hibernate only considers the base class `@Cacheable` and `@Cache` definition.
|
As of Hibernate ORM 5.3, it's now possible to possible to override a base class `@Cacheable` or `@Cache` definition in subclasses.
|
||||||
|
|
||||||
|
However, the Hibernate cache concurrency strategy (e.g. read-only, nonstrict-read-write, read-write, transactional) is still defined at the root entity level
|
||||||
|
and cannot be overridden.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
Nevertheless, the reasons why we advise you to have all entities belonging to an inheritance tree share the same caching definition can be summed as follows:
|
||||||
|
|
||||||
|
- from a performance perspective, adding an additional check on a per entity type level slows the bootstrap process.
|
||||||
|
- providing different caching semantics for subclasses would violate the https://en.wikipedia.org/wiki/Liskov_substitution_principle[Liskov substitution principle].
|
||||||
|
|
||||||
[[caching-query]]
|
[[caching-query]]
|
||||||
=== Entity cache
|
=== Entity cache
|
||||||
|
|
||||||
|
|
|
@ -779,7 +779,7 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
Date timestamp = new Date( );
|
Date timestamp = new Date( );
|
||||||
Session session = entityManager.unwrap( Session.class );
|
Session session = entityManager.unwrap( Session.class );
|
||||||
//tag::hql-api-positional-parameter-example[]56:37
|
//tag::hql-api-positional-parameter-example[]
|
||||||
org.hibernate.query.Query query = session.createQuery(
|
org.hibernate.query.Query query = session.createQuery(
|
||||||
"select p " +
|
"select p " +
|
||||||
"from Person p " +
|
"from Person p " +
|
||||||
|
|
Loading…
Reference in New Issue