From 74a9acc616f2329e7d38d96571130525388b86e4 Mon Sep 17 00:00:00 2001 From: Vlad Mihalcea Date: Mon, 3 Oct 2016 15:19:31 +0300 Subject: [PATCH] HHH-11142 - Document supported use/implications of @Cache / @Cacheable (cherry picked from commit 88bc2db28a10222fbc3676cf11da7be88651cf1a) --- .../userguide/chapters/caching/Caching.adoc | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/documentation/src/main/asciidoc/userguide/chapters/caching/Caching.adoc b/documentation/src/main/asciidoc/userguide/chapters/caching/Caching.adoc index bd33a3f08f..1ddde1502b 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/caching/Caching.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/caching/Caching.adoc @@ -118,6 +118,53 @@ include:: The default value is `all` so lazy properties are cacheable. The other possible value is `non-lazy` so lazy properties are not cacheable. +[[caching-mappings-inheritance]] +=== 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. +That being said, it is not possible to customize the base class `@Cacheable` or `@Cache` definition in subclasses. + +Although the JPA 2.1 specification says that the `@Cacheable` annotation could be overwritten by a subclass: + +[quote, Section 11.1.7 of the JPA 2.1 Specification] +____ +The value of the `Cacheable` annotation is inherited by subclasses; it can be +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] +==== +Because of all these intricacies, Hibernate only considers the base class `@Cacheable` and `@Cache` definition. +==== + [[caching-query]] === Entity cache