[[caching]]
== Caching
:sourcedir: ../../../../../test/java/org/hibernate/userguide/caching

At runtime, Hibernate handles moving data into and out of the second-level cache in response to the operations performed by the `Session`, which acts as a transaction-level cache of persistent data.
Once an entity becomes managed, that object is added to the internal cache of the current persistence context (`EntityManager` or `Session`).
The persistence context is also called the first-level cache, and it's enabled by default.

It is possible to configure a JVM-level (`SessionFactory`-level) or even a cluster cache on a class-by-class and collection-by-collection basis.

[NOTE]
====
Be aware that caches are not aware of changes made to the persistent store by other applications.
They can, however, be configured to regularly expire cached data.
====

[[caching-config]]
=== Configuring second-level caching

Hibernate can integrate with various caching providers for the purpose of caching data outside the context of a particular `Session`.
This section defines the settings which control this behavior.

[[caching-config-provider]]
==== RegionFactory

`org.hibernate.cache.spi.RegionFactory` defines the integration between Hibernate and a pluggable caching provider.
`hibernate.cache.region.factory_class` is used to declare the provider to use.
Hibernate comes with built-in support for two popular caching libraries: <<caching-provider-ehcache,Ehcache>> and <<caching-provider-infinispan,Infinispan>>.
Detailed information is provided later in this chapter.

[[caching-config-properties]]
==== Caching configuration properties

Besides specific provider configuration, there are a number of configurations options on the Hibernate side of the integration that control various caching behaviors:

`hibernate.cache.use_second_level_cache`::
	Enable or disable second level caching overall. Default is true, although the default region factory is `NoCachingRegionFactory`.
`hibernate.cache.use_query_cache`::
	Enable or disable second level caching of query results. Default is false.
`hibernate.cache.query_cache_factory`::
	Query result caching is handled by a special contract that deals with staleness-based invalidation of the results.
	The default implementation does not allow stale results at all. Use this for applications that would like to relax that.
	Names an implementation of `org.hibernate.cache.spi.QueryCacheFactory`
`hibernate.cache.use_minimal_puts`::
	Optimizes second-level cache operations to minimize writes, at the cost of more frequent reads. Providers typically set this appropriately.
`hibernate.cache.region_prefix`::
	Defines a name to be used as a prefix to all second-level cache region names.
`hibernate.cache.default_cache_concurrency_strategy`::
	In Hibernate second-level caching, all regions can be configured differently including the concurrency strategy to use when accessing that particular region.
	This setting allows to define a default strategy to be used.
	This setting is very rarely required as the pluggable providers do specify the default strategy to use.
	Valid values include:
* read-only,
* read-write,
* nonstrict-read-write,
* transactional
`hibernate.cache.use_structured_entries`::
	If `true`, forces Hibernate to store data in the second-level cache in a more human-friendly format.
	Can be useful if you'd like to be able to "browse" the data directly in your cache, but does have a performance impact.
`hibernate.cache.auto_evict_collection_cache`::
	Enables or disables the automatic eviction of a bidirectional association's collection cache entry when the association is changed just from the owning side.
	This is disabled by default, as it has a performance impact to track this state.
	However if your application does not manage both sides of bidirectional association where the collection side is cached,
	the alternative is to have stale data in that collection cache.
`hibernate.cache.use_reference_entries`::
	Enable direct storage of entity references into the second level cache for read-only or immutable entities.
`hibernate.cache.keys_factory`::
    When storing entries into second-level cache as key-value pair, the identifiers can be wrapped into tuples
    <entity type, tenant, identifier> to guarantee uniqueness in case that second-level cache stores all entities
    in single space. These tuples are then used as keys in the cache. When the second-level cache implementation
    (incl. its configuration) guarantees that different entity types are stored separately and multi-tenancy is not
    used, you can omit this wrapping to achieve better performance. Currently, this property is only supported when
    Infinispan is configured as the second-level cache implementation. Valid values are:
* `default` (wraps identitifers in the tuple)
* `simple` (uses identifiers as keys without any wrapping)
* fully qualified class name that implements `org.hibernate.cache.spi.CacheKeysFactory`

[[caching-mappings]]
=== Configuring second-level cache mappings

The cache mappings can be configured via JPA annotations or XML descriptors or using the Hibernate-specific mapping files.

By default, entities are not part of the second level cache and we recommend you to stick to this setting.
However, you can override this by setting the `shared-cache-mode` element in your `persistence.xml` file
or by using the `javax.persistence.sharedCache.mode` property in your configuration file.
The following values are possible:

`ENABLE_SELECTIVE` (Default and recommended value)::
	Entities are not cached unless explicitly marked as cacheable (with the https://docs.oracle.com/javaee/7/api/javax/persistence/Cacheable.html[`@Cacheable`] annotation).
`DISABLE_SELECTIVE`::
	Entities are cached unless explicitly marked as non-cacheable.
`ALL`::
	Entities are always cached even if marked as non-cacheable.
`NONE`::
	No entity is cached even if marked as cacheable.
	This option can make sense to disable second-level cache altogether.

The cache concurrency strategy used by default can be set globally via the `hibernate.cache.default_cache_concurrency_strategy` configuration property.
The values for this property are:

read-only::
	If your application needs to read, but not modify, instances of a persistent class, a read-only cache is the best choice.
	Application can still delete entities and these changes should be reflected in second-level cache so that the cache
	does not provide stale entities.
	Implementations may use performance optimizations based on the immutability of entities.
read-write::
	If the application needs to update data, a read-write cache might be appropriate.
	This strategy provides consistent access to single entity, but not a serializable transaction isolation level; e.g. when TX1 reads looks up an entity and does not find it, TX2 inserts the entity into cache and TX1 looks it up again, the new entity can be read in TX1.
nonstrict-read-write::
    Similar to read-write strategy but there might be occasional stale reads upon concurrent access to an entity. The choice of this strategy might be appropriate if the application rarely updates the same data simultaneously and strict transaction isolation is not required. Implementations may use performance optimizations that make use of the relaxed consistency guarantee.
transactional::
    Provides serializable transaction isolation level.

[NOTE]
====
Rather than using a global cache concurrency strategy, it is recommended to define this setting on a per entity basis.
Use the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/Cache.html[`@org.hibernate.annotations.Cache`] annotation for that.
====

The `@Cache` annotation define three attributes:

usage::
	Defines the `CacheConcurrencyStrategy`
region::
	Defines a cache region where entries will be stored
include::
	If lazy properties should be included in the second level cache.
	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

[[caching-entity-mapping-example]]
.Entity cache mapping
====
[source, JAVA, indent=0]
----
include::{sourcedir}/NonStrictReadWriteCacheTest.java[tags=caching-entity-mapping-example]
----
====

Hibernate stores cached entities in a dehydrated form, which is similar to the database representation.
Aside from the foreign key column values of the `@ManyToOne` or `@OneToOne` child-side associations,
entity relationships are not stored in the cache,

Once an entity is stored in the second-level cache, you can avoid a database hit and load the entity from the cache alone:

[[caching-entity-jpa-example]]
.Loading entity using JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-entity-jpa-example]
----
====

[[caching-entity-native-example]]
.Loading entity using Hibernate native API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-entity-native-example]
----
====

The Hibernate second-level cache can also load entities by their <<chapters/domain/natural_id.adoc#naturalid,natural id>>:

[[caching-entity-natural-id-mapping-example]]
.Hibernate natural id entity mapping
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-entity-natural-id-mapping-example]
----
====

[[caching-entity-natural-id-example]]
.Loading entity using Hibernate native natural id API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-entity-natural-id-example]
----
====

[[caching-collection]]
=== Collection cache

Hibernate can also cache collections, and the `@Cache` annotation must be on added to the collection property.

If the collection is made of value types (basic or embeddables mapped with `@ElementCollection`),
the collection is stored as such.
If the collection contains other entities (`@OneToMany` or `@ManyToMany`),
the collection cache entry will store the entity identifiers only.

[[caching-collection-mapping-example]]
.Collection cache mapping
====
[source, JAVA, indent=0]
----
include::{sourcedir}/NonStrictReadWriteCacheTest.java[tags=caching-collection-mapping-example]
----
====

Collections are read-through, meaning they are cached upon being accessed for the first time:

[[caching-collection-example]]
.Collection cache usage
====
[source, JAVA, indent=0]
----
include::{sourcedir}/NonStrictReadWriteCacheTest.java[tags=caching-collection-example]
----
====

Subsequent collection retrievals will use the cache instead of going to the database.

[NOTE]
====
The collection cache is not write-through so any modification will trigger a collection cache entry invalidation.
On a subsequent access, the collection will be loaded from the database and re-cached.
====

[[caching-query]]
=== Query cache

Aside from caching entities and collections, Hibernate offers a query cache too.
This is useful for frequently executed queries with fixed parameter values.

[NOTE]
====
Caching of query results introduces some overhead in terms of your applications normal transactional processing.
For example, if you cache results of a query against `Person`,
Hibernate will need to keep track of when those results should be invalidated because changes have been committed against any `Person` entity.

That, coupled with the fact that most applications simply gain no benefit from caching query results,
leads Hibernate to disable caching of query results by default.
====

To use query caching, you will first need to enable it with the following configuration property:

[[caching-query-configuration]]
.Enabling query cache
====
[source, XML, indent=0]
----
<property
    name="hibernate.cache.use_query_cache"
    value="true" />
----
====

As mentioned above, most queries do not benefit from caching or their results.
So by default, individual queries are not cached even after enabling query caching.
Each particular query that needs to be cached must be manually set as cacheable.
This way, the query looks for existing cache results or adds the query results to the cache when being executed.

[[caching-query-jpa-example]]
.Caching query using JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-query-jpa-example]
----
====

[[caching-query-native-example]]
.Caching query using Hibernate native API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-query-native-example]
----
====

[NOTE]
====
The query cache does not cache the state of the actual entities in the cache;
it caches only identifier values and results of value type.

Just as with collection caching, the query cache should always be used in conjunction with the second-level cache for those entities expected to be cached as part of a query result cache.
====

[[caching-query-region]]
==== Query cache regions

This setting creates two new cache regions:

`org.hibernate.cache.internal.StandardQueryCache`::
	Holding the cached query results
`org.hibernate.cache.spi.UpdateTimestampsCache`::
	Holding timestamps of the most recent updates to queryable tables.
	These are used to validate the results as they are served from the query cache.

[IMPORTANT]
====
If you configure your underlying cache implementation to use expiration, it's very important that the timeout of the underlying cache region for the `UpdateTimestampsCache` is set to a higher value than the timeouts of any of the query caches.

In fact, we recommend that the `UpdateTimestampsCache` region is not configured for expiration (time-based) or eviction (size/memory-based) at all.
Note that an LRU (Least Recently Used) cache eviction policy is never appropriate for this particular cache region.
====

If you require fine-grained control over query cache expiration policies,
you can specify a named cache region for a particular query.

[[caching-query-region-jpa-example]]
.Caching query in custom region using JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-query-region-jpa-example]
----
====

[[caching-query-region-native-example]]
.Caching query in custom region using Hibernate native API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-query-region-native-example]
----
====

If you want to force the query cache to refresh one of its regions (disregarding any cached results it finds there),
you can use custom cache modes.

[[caching-query-region-store-mode-jpa-example]]
.Using custom query cache mode with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-query-region-store-mode-jpa-example]
----
====

[[caching-query-region-native-example]]
.Using custom query cache mode with Hibernate native API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-query-region-store-mode-native-example]
----
====

[NOTE]
====
When using http://docs.oracle.com/javaee/7/api/javax/persistence/CacheStoreMode.html#REFRESH[`CacheStoreMode.REFRESH`] or https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/CacheMode.html#REFRESH[`CacheMode.REFRESH`] in conjunction with the region you have defined for the given query,
Hibernate will selectively force the results cached in that particular region to be refreshed.

This is particularly useful in cases where underlying data may have been updated via a separate process
and is a far more efficient alternative to bulk eviction of the region via `SessionFactory` eviction which looks as follows:

[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-query-region-native-evict-example]
----

====

[[caching-management]]
=== Managing the cached data

Traditionally, Hibernate defined the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/CacheMode.html[`CacheMode`] enumeration to describe
the ways of interactions with the cached data.
JPA split cache modes by storage (http://docs.oracle.com/javaee/7/api/javax/persistence/CacheStoreMode.html[`CacheStoreMode`])
and retrieval (http://docs.oracle.com/javaee/7/api/javax/persistence/CacheRetrieveMode.html[`CacheRetrieveMode`]).

The relationship between Hibernate and JPA cache modes can be seen in the following table:

.Cache modes relationships
[cols=",,,",options="header",]
|======================================
|Hibernate 			 | JPA | Description
|`CacheMode.NORMAL`  |`CacheStoreMode.USE` and `CacheRetrieveMode.USE` | Default. Reads/writes data from/into cache
|`CacheMode.REFRESH` |`CacheStoreMode.REFRESH` and `CacheRetrieveMode.BYPASS` | Doesn't read from cache, but writes to the cache upon loading from the database
|`CacheMode.PUT`     |`CacheStoreMode.USE` and `CacheRetrieveMode.BYPASS` | Doesn't read from cache, but writes to the cache as it reads from the database
|`CacheMode.GET`     |`CacheStoreMode.BYPASS` and `CacheRetrieveMode.USE` | Read from the cache, but doesn't write to cache
|`CacheMode.IGNORE`  |`CacheStoreMode.BYPASS` and `CacheRetrieveMode.BYPASS` | Doesn't read/write data from/into cache
|======================================

Setting the cache mode can be done either when loading entities directly or when executing a query.

[[caching-management-cache-mode-entity-jpa-example]]
.Using custom cache modes with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-management-cache-mode-entity-jpa-example]
----
====

[[caching-management-cache-mode-entity-native-example]]
.Using custom cache modes with Hibernate native API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-management-cache-mode-entity-native-example]
----
====

The custom cache modes can be set for queries as well:

[[caching-management-cache-mode-query-jpa-example]]
.Using custom cache modes for queries with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-management-cache-mode-query-jpa-example]
----
====

[[caching-management-cache-mode-query-native-example]]
.Using custom cache modes for queries with Hibernate native API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-management-cache-mode-query-native-example]
----
====

[[caching-management-evict]]
==== Evicting cache entries

Because the second level cache is bound to the `EntityManagerFactory` or the `SessionFactory`,
cache eviction must be done through these two interfaces.

JPA only supports entity eviction through the https://docs.oracle.com/javaee/7/api/javax/persistence/Cache.html[`javax.persistence.Cache`] interface:

[[caching-management-evict-jpa-example]]
.Evicting entities with JPA
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-management-evict-jpa-example]
----
====

Hibernate is much more flexible in this regard as it offers fine-grained control over what needs to be evicted.
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/Cache.html[`org.hibernate.Cache`] interface defines various evicting strategies:

- entities (by their class or region)
- entities stored using the natural-id (by their class or region)
- collections (by the region, and it might take the collection owner identifier as well)
- queries (by region)

[[caching-management-evict-native-example]]
.Evicting entities with Hibernate native API
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-management-evict-native-example]
----
====

[[caching-statistics]]
=== Caching statistics

If you enable the `hibernate.generate_statistics` configuration property,
Hibernate will expose a number of metrics via `SessionFactory.getStatistics()`.
Hibernate can even be configured to expose these statistics via JMX.

This way, you can get access to the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/stat/Statistics.html[`Statistics`] class which comprises all sort of
second-level cache metrics.

[[caching-statistics-example]]
.Caching statistics
====
[source, JAVA, indent=0]
----
include::{sourcedir}/SecondLevelCacheTest.java[tags=caching-statistics-example]
----
====


[[caching-provider-ehcache]]
=== Ehcache

[NOTE]
====
Use of the build-in integration for http://www.ehcache.org/[Ehcache] requires that the `hibernate-ehcache` module jar (and all of its dependencies) are on the classpath.
====

[[caching-provider-ehcache-region-factory]]
==== RegionFactory

The hibernate-ehcache module defines two specific region factories: `EhCacheRegionFactory` and `SingletonEhCacheRegionFactory`.

[[caching-provider-ehcache-region-factory-shared]]
===== `EhCacheRegionFactory`

To use the `EhCacheRegionFactory`, you need to specify the following configuration property:

[[caching-provider-ehcache-region-factory-shared-example]]
.`EhCacheRegionFactory` configuration
====
[source, XML, indent=0]
----
<property
    name="hibernate.cache.region.factory_class"
    value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
----
====

The `EhCacheRegionFactory` configures a `net.sf.ehcache.CacheManager` for each `SessionFactory`,
so the `CacheManager` is not shared among multiple `SessionFactory` instances in the same JVM.

[[caching-provider-ehcache-region-factory-singleton]]
===== `SingletonEhCacheRegionFactory`

To use the `SingletonEhCacheRegionFactory`, you need to specify the following configuration property:

[[caching-provider-ehcache-region-factory-singleton-example]]
.`SingletonEhCacheRegionFactory` configuration
====
[source, XML, indent=0]
----
<property
    name="hibernate.cache.region.factory_class"
    value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/>
----
====

The `SingletonEhCacheRegionFactory` configures a singleton `net.sf.ehcache.CacheManager` (see http://www.ehcache.org/apidocs/2.8.4/net/sf/ehcache/CacheManager.html#create%28%29[CacheManager#create()]),
shared among multiple `SessionFactory` instances in the same JVM.

[NOTE]
====
http://www.ehcache.org/documentation/2.8/integrations/hibernate#optional[Ehcache documentation] recommends using multiple non-singleton `CacheManager(s)` when there are multiple Hibernate `SessionFactory` instances running in the same JVM.
====

[[caching-provider-infinispan]]
=== Infinispan

[NOTE]
====
Use of the build-in integration for http://infinispan.org/[Infinispan] requires that the `hibernate-infinispan module` jar (and all of its dependencies) are on the classpath.
====

Infinispan currently supports all cache concurrency modes, although not all combinations of configurations are compatible.

Traditionally the `transactional` and `read-only` strategy was supported on _transactional invalidation_ caches. In version 5.0, further modes have been added:

* _non-transactional invalidation_ caches are supported as well with `read-write` strategy. The actual setting of cache concurrency mode (`read-write` vs. `transactional`) is not honored, the appropriate strategy is selected based on the cache configuration (_non-transactional_ vs. _transactional_).
* `read-write` mode is supported on _non-transactional distributed/replicated_ caches, however, eviction should not be used in this configuration. Use of eviction can lead to consistency issues. Expiration (with reasonably long max-idle times) can be used.
* `nonstrict-read-write` mode is supported on _non-transactional distributed/replicated_ caches, but the eviction should be turned off as well. In addition to that, the entities must use versioning. This mode mildly relaxes the consistency - between DB commit and end of transaction commit a stale read (see <<caching-provider-infinispan-stale-read-example,example>>) may occur in another transaction. However this strategy uses less RPCs and can be more performant than the other ones.
* `read-only` mode is supported on both _transactional_ and _non-transactional_ _invalidation_ caches and _non-transactional distributed/replicated_ caches, but use of this mode currently does not bring any performance gains.

The available combinations are summarized in table below:

[[caching-provider-infinispan-compatibility-table]]
.Cache concurrency strategy/cache mode compatibility table
[options="header"]
|===
|Concurrency strategy|Cache transactions|Cache mode             |Eviction
|transactional       |transactional     |invalidation           |yes
|read-write          |non-transactional |invalidation           |yes
|read-write          |non-transactional |distributed/replicated |no
|nonstrict-read-write|non-transactional |distributed/replicated |no
|===

If your second level cache is not clustered, it is possible to use local cache instead of the clustered caches in all modes as described above.

[[caching-provider-infinispan-stale-read-example]]
.Stale read with `nonstrict-read-write` strategy
====
[source, indent=0]
----
A=0 (non-cached), B=0 (cached in 2LC)
TX1: write A = 1, write B = 1
TX1: start commit
TX1: commit A, B in DB
TX2: read A = 1 (from DB), read B = 0 (from 2LC) // breaks transactional atomicity
TX1: update A, B in 2LC
TX1: end commit
Tx3: read A = 1, B = 1 // reads after TX1 commit completes are consistent again
----
====

[[caching-provider-infinispan-region-factory]]
==== RegionFactory

The hibernate-infinispan module defines two specific providers: `infinispan` and  `infinispan-jndi`.

[[caching-provider-infinispan-region-factory-basic]]
===== `InfinispanRegionFactory`

If Hibernate and Infinispan are running in a standalone environment, the `InfinispanRegionFactory` should be configured as follows:

[[caching-provider-infinispan-region-factory-basic-example]]
.`InfinispanRegionFactory` configuration
====
[source, XML, indent=0]
----
<property
    name="hibernate.cache.region.factory_class"
    value="org.hibernate.cache.infinispan.InfinispanRegionFactory" />
----
====

[[caching-provider-infinispan-region-factory-jndi]]
===== `JndiInfinispanRegionFactory`

If the Infinispan `CacheManager` is bound to JNDI, then the `JndiInfinispanRegionFactory` should be used as a region factory:

[[caching-provider-infinispan-region-factory-jndi-example]]
.`JndiInfinispanRegionFactory` configuration
====
[source, XML, indent=0]
----
<property
    name="hibernate.cache.region.factory_class"
    value="org.hibernate.cache.infinispan.JndiInfinispanRegionFactory" />

<property
    name="hibernate.cache.infinispan.cachemanager"
    value="java:CacheManager" />
----
====

===== Infinispan in JBoss AS/WildFly

When using JPA in WildFly, region factory is automatically set upon configuring `hibernate.cache.use_second_level_cache=true` (by default second-level cache is not used).
For more information, please consult https://docs.jboss.org/author/display/WFLY9/JPA+Reference+Guide#JPAReferenceGuide-UsingtheInfinispansecondlevelcache[WildFly documentation].

[[caching-provider-infinispan-config]]
==== Configuration properties

Hibernate-infinispan module comes with default configuration in `infinispan-config.xml` that is suited for clustered use. If there's only single instance accessing the DB, you can use more performant `infinispan-config-local.xml` by setting the `hibernate.cache.infinispan.cfg` property. If you require further tuning of the cache, you can provide your own configuration. Caches that are not specified in the provided configuration will default to `infinispan-config.xml` (if the provided configuration uses clustering) or `infinispan-config-local.xml`. It is not possible to specify the configuration this way in WildFly.

[[caching-provider-infinispan-config-example]]
.Use custom Infinispan configuration
====
[source, XML, indent=0]
----
<property
    name="hibernate.cache.infinispan.cfg"
    value="my-infinispan-configuration.xml" />
====

[NOTE]
====
If the cache is configured as transactional, InfinispanRegionFactory automatically sets transaction manager so that the TM used by Infinispan is the same as TM used by Hibernate.
====


Cache configuration can differ for each type of data stored in the cache. In order to override the cache configuration template, use property `hibernate.cache.infinispan._data-type_.cfg` where `_data-type_` can be one of:

`entity`:: Entities indexed by `@Id` or `@EmbeddedId` attribute.
`immutable-entity`:: Entities tagged with `@Immutable` annotation or set as `mutable=false` in mapping file.
`naturalid`:: Entities indexed by their `@NaturalId` attribute.
`collection`:: All collections.
`timestamps`:: Mapping _entity type_ -> _last modification timestamp_. Used for query caching.
`query`:: Mapping _query_ -> _query result_.
`pending-puts`:: Auxiliary caches for regions using invalidation mode caches.

For specifying cache template for specific region, use region name instead of the `_data-type_`:

[[caching-provider-infinispan-config-cache-example]]
.Use custom cache template
====
[source, XML, indent=0]
----
<property
    name="hibernate.cache.infinispan.entities.cfg"
    value="custom-entities" />
<property
    name="hibernate.cache.infinispan.query.cfg"
    value="custom-query-cache" />
<property
    name="hibernate.cache.infinispan.com.example.MyEntity.cfg"
    value="my-entities" />
<property
    name="hibernate.cache.infinispan.com.example.MyEntity.someCollection.cfg"
    value="my-entities-some-collection" />
====

[IMPORTANT]
====
Cache configurations are used only as a template for the cache created for given region (usually each entity hierarchy or collection has its own region). It is not possible to use the same cache for different regions.
====

Some options in the cache configuration can also be overridden directly through properties. These are:

`hibernate.cache.infinispan._something_.eviction.strategy`:: Available options are `NONE`, `LRU` and `LIRS`.
`hibernate.cache.infinispan._something_.eviction.max_entries`:: Maximum number of entries in the cache.
`hibernate.cache.infinispan._something_.expiration.lifespan`:: Lifespan of entry from insert into cache (in milliseconds)
`hibernate.cache.infinispan._something_.expiration.max_idle`:: Lifespan of entry from last read/modification (in milliseconds)
`hibernate.cache.infinispan._something_.expiration.wake_up_interval`:: Period of thread checking expired entries.
`hibernate.cache.infinispan.statistics`:: Globally enables/disable Infinispan statistics collection, and their exposure via JMX.

[NOTE]
====
In versions prior to 5.1, `hibernate.cache.infinispan._something_.expiration.wake_up_interval` was called `hibernate.cache.infinispan._something_.eviction.wake_up_interval`.
Eviction settings are checked upon each cache insert, it is expiration that needs to be triggered periodically.
The old property still works, but its use is deprecated.
====

[NOTE]
====
Property `hibernate.cache.infinispan.use_synchronization` that allowed to register Infinispan as XA resource in the transaction has been deprecated in 5.0 and is not honored anymore. Infinispan 2LC must register as synchronizations on transactional caches. Also, non-transactional cache modes hook into the current JTA/JDBC transaction as synchronizations.
====

[[caching-provider-infinispan-config-query-timestamps]]
===== Configuring Query and Timestamps caches

Since version 5.0 it is possible to configure query caches as _non-transactional_. Consistency guarantees are not changed and writes to the query cache should be faster.

The query cache is configured so that queries are only cached locally . Alternatively, you can configure query caching to use replication by selecting the "replicated-query" as query cache name. However, replication for query cache only makes sense if, and only if, all of this conditions are true:

* Performing the query is quite expensive.
* The same query is very likely to be repeatedly executed on different cluster nodes.
* The query is unlikely to be invalidated out of the cache

[NOTE]
====
Hibernate must aggressively invalidate query results from the cache any time any instance of one of the entity types is modified. All cached query results referencing given entity type are invalidated, even if the change made to the specific entity instance would not have affected the query result.
The timestamps cache plays here an important role - it contains last modification timestamp for each entity type. After a cached query results is loaded, its timestamp is compared to all timestamps of the entity types that are referenced in the query and if any of these is higher, the cached query result is discarded and the query is executed against DB.
====

In default configuration, timestamps cache is asynchronously replicated. This means that a cached query on remote node can provide stale results for a brief time window before the remote timestamps cache is updated. However, requiring synchronous RPC would result in severe performance degradation.

Further, but possibly outdated information can be found in http://infinispan.org/docs/8.0.x/user_guide/user_guide.html#_using_infinispan_as_jpa_hibernate_second_level_cache_provider[Infinispan documentation].

