Hibernate 3.3 | Quick Start | Enabling Ehcache | Mapping Files | ehcache.xml| Demo Apps | FAQ | Performance Tips | How to Scale | Download
Ehcache easily integrates with the Hibernate Object/Relational persistence and query service. Gavin King, the maintainer of Hibernate, is also a committer to the Ehcache project. This ensures Ehcache will remain a first class cache for Hibernate.
Note these instructions are for Hibernate 3. Go to Guide for Version 1.1 for older instructions on how to use Hibernate 2.1.
The net.sf.ehcache.hibernate package provides classes integrating Ehcache with Hibernate.

The Hibernate 3.2 caching SPI is deprecated from Hibernate 3.3 up. Ehcache 2.0 introduces a new Hibernate 3.3 SPI implementation. The SPI changes further in Hibernate 3.5. The Ehcache implementation is forward compatible with Hibernate 3.5 too.
The EhCacheProvider class, which implements the 3.2 API is provided for backward compatibility. Anyone already using Ehcache with Hibernate will be using this version. We encourage you to upgrade to the new class, EhCacheRegionFactory in preparation for when Hibernate drops support for the old SPI. In recognition of this, we have marked EhCacheProvider as deprecated.
The new cache region factory takes advantage of the new SPI to provide higher performance. The old SPI had heavy synchronization to ensure all of the different caching providers were thread-safe. The new SPI leaves that to the implementer. Ehcache does not require extra synchronization, so this overhead is avoided.
In September 2009 Terracotta released its Hibernate Caching Provider which was set as follows:
<property name="hibernate.cache.provider_class">org.terracotta.hibernate.TerracottaHibernateCacheProvider</property>
It features high performance clustered Hibernate caching using the Terracotta Server Array.
The new 3.3 EhCacheRegionFactory replaces that provider and the old Ehcache provider - it is a superset of both and also implements the new SPI. The Hibernate provider required a Java agent. That is not required in the new provider.
We recommend existing Terracotta Hibernate users upgrade to the Ehcache 2.0 provider.
hibernate.cache.use_minimal_puts - minimalPuts is the equivalent of putIfAbsent; an item is only put in the cache if it does not exist. It is an optimisation for clustered caches. This is off by default but can be set to true in Hibernate's properties when using Ehcache with the Terracotta Server Array (Ehcache EX and FX) for better performance.
net.sf.ehcache.hibernate.CacheLockTimeoutSeconds - when Hibernate is controlling transactions and a cache is configured for read/write access, Hibernate will "soft lock" the cache entries during the database writes. There is a timeout on these locks that is set by default to 60 seconds. If the lock times out before the write completes, then the cache entry will be evicted causing Hibernate to reload it when required. If you get lock timeout exceptions consider increasing the lock tieout with this property.
Follow these steps to get up and running quickly:
Each of these steps is illustrated using a fictional Country Domain Object.
For more about cache configuration in Hibernate see the Hibernate documentation. Parts of this chapter are drawn from Hibernate documentation and source code comments.
They are reproduced here for convenience in using ehcache.
To ensure Ehcache is enabled, verify that the Hibernate cache provider or region factory property is set to one of the following in the Hibernate configuration file, either hibernate.cfg.xml or hibernate.properties. The format given is for hibernate.cfg.xml.
Use:
<property name="hibernate.cache.region.factory_class">
net.sf.ehcache.hibernate.EhCacheRegionFactory
</property>
for instance creation, or
<property name="hibernate.cache.region.factory_class">
net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory
</property>
to force Hibernate to use a singleton of Ehcache CacheManager.
Use:
<property name="hibernate.cache.provider_class">
net.sf.ehcache.hibernate.EhCacheProvider
</property>
for instance creation, or
<property name="hibernate.cache.provider_class">
net.sf.ehcache.hibernate.SingletonEhCacheProvider
</property>
to force Hibernate to use a singleton Ehcache CacheManager.
The configurationResourceName property is used to specify the location of the ehcache configuration file to be used with the given Hibernate instance and cache provider/region-factory.
hibernate.cache.region.factory_class=net.sf.ehcache.hibernate.EhCacheRegionFactory net.sf.ehcache.configurationResourceName=/name_of_ehcache.xml
net.sf.ehcache.configurationResourceName - The name of a configuration resource to use.
The resource is searched for in the root of the classpath. It is needed to support multiple CacheManagers in the same VM. It tells Hibernate which configuration to use. An example might be "ehcache-2.xml".
When using multiple Hibernate instances it is therefore recommended to use multiple non-singleton providers or region factories, each with a dedicated Ehcache configuration resource.
The provider can also be set programmatically in Hibernate by adding necessary Hibernate property settings to the configuration before creating the SessionFactory: --- Configuration.setProperty("hibernate.cache.region.factory_class", "net.sf.ehcache.hibernate.EhCacheRegionFactory"). ---
In Hibernate, each domain object requires a mapping file.
For example to enable cache entries for the domain object com.somecompany.someproject.domain.Country there would be a mapping file something like the following:
<hibernate-mapping>
<class
name="com.somecompany.someproject.domain.Country"
table="ut_Countries"
dynamic-update="false"
dynamic-insert="false"
>
...
</hibernate-mapping>
To enable caching, add the following element.
<cache usage="read-write|nonstrict-read-write|read-only" />
e.g.
<cache usage="read-write" />
Caches data that is sometimes updated while maintaining the semantics of "read committed" isolation level. If the database is set to "repeatable read", this concurrency strategy almost maintains the semantics. Repeatable read isolation is compromised in the case of concurrent writes.
This is an "asynchronous" concurrency strategy.
Caches data that is sometimes updated without ever locking the cache. If concurrent access to an item is possible, this concurrency strategy makes no guarantee that the item returned from the cache is the latest version available in the database. Configure your cache timeout accordingly! This is an "asynchronous" concurrency strategy.
Caches data that is never updated.
Because ehcache.xml has a defaultCache, caches will always be created when required by Hibernate. However more control can be exerted by specifying a configuration per cache, based on its name.
In particular, because Hibernate caches are populated from databases, there is potential for them to get very large. This can be controlled by capping their maxElementsInMemory and specifying whether to overflowToDisk beyond that.
Hibernate uses a specific convention for the naming of caches of Domain Objects, Collections, and Queries.
Hibernate creates caches named after the fully qualified name of Domain Objects.
So, for example to create a cache for com.somecompany.someproject.domain.Country create a cache configuration entry similar to the following in ehcache.xml.
<cache
name="com.somecompany.someproject.domain.Country"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
CacheConcurrencyStrategy read-write, nonstrict-read-write and read-only policies apply to Domain Objects.
Hibernate creates collection caches named after the fully qualified name of the Domain Object followed by "." followed by the collection field name.
For example, a Country domain object has a set of advancedSearchFacilities. The Hibernate doclet for the accessor looks like:
/**
* Returns the advanced search facilities that should appear for this country.
* @hibernate.set cascade="all" inverse="true"
* @hibernate.collection-key column="COUNTRY_ID"
* @hibernate.collection-one-to-many class="com.wotif.jaguar.domain.AdvancedSearchFacility"
* @hibernate.cache usage="read-write"
*/
public Set getAdvancedSearchFacilities() {
return advancedSearchFacilities;
}
You need an additional cache configured for the set. The ehcache.xml configuration looks like:
<cache name="com.somecompany.someproject.domain.Country"
maxElementsInMemory="50"
eternal="false"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<cache
name="com.somecompany.someproject.Country.advancedSearchFacilities"
maxElementsInMemory="450"
eternal="false"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
read-write, nonstrict-read-write and read-only policies apply to Domain Object collections.
Hibernate allows the caching of query results using two caches.
"net.sf.hibernate.cache.StandardQueryCache" and "net.sf.hibernate.cache.UpdateTimestampsCache" in versions 2.1 to 3.1 and "org.hibernate.cache.StandardQueryCache" and "org.hibernate.cache.UpdateTimestampsCache" in version 3.2. are always used.
This cache is used if you use a query cache without setting a name. A typical ehcache.xml configuration is:
<cache
name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="5"
eternal="false"
timeToLiveSeconds="120"
overflowToDisk="true"/>
Tracks the timestamps of the most recent updates to particular tables. It is important that the cache timeout of the underlying cache implementation be set to a higher value than the timeouts of any of the query caches. In fact, it is recommend that the the underlying cache not be configured for expiry at all.
A typical ehcache.xml configuration is:
<cache
name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="true"/>
In addition, a QueryCache can be given a specific name in Hibernate using Query.setCacheRegion(String name). The name of the cache in ehcache.xml is then the name given in that method. The name can be whatever you want, but by convention you should use "query." followed by a descriptive name.
E.g.
<cache name="query.AdministrativeAreasPerCountry"
maxElementsInMemory="5"
eternal="false"
timeToLiveSeconds="86400"
overflowToDisk="true"/>
For example, let's say we have a common query running against the Country Domain.
Code to use a query cache follows:
public List getStreetTypes(final Country country) throws HibernateException {
final Session session = createSession();
try {
final Query query = session.createQuery(
"select st.id, st.name"
+ " from StreetType st "
+ " where st.country.id = :countryId "
+ " order by st.sortOrder desc, st.name");
query.setLong("countryId", country.getId().longValue());
query.setCacheable(true);
query.setCacheRegion("query.StreetTypes");
return query.list();
} finally {
session.close();
}
}
The query.setCacheable(true) line caches the query.
The query.setCacheRegion("query.StreetTypes") line sets the name of the Query Cache.
None of read-write, nonstrict-read-write and read-only policies apply to Domain Objects. Cache policies are not configurable for query cache. They act like a non-locking read only cache.
We have demo applications showing how to use the Hibernate 3.3 CacheRegionFactory.
Check out from https://svn.terracotta.org/repo/forge/projects/hibernate-tutorial-web/trunk (Terracotta Community Login Required)
Examinator is our complete application that shows many aspects of caching, all using the Terracotta Server Array.
Check out from https://svn.terracotta.org/svn/forge/projects/exam/ (Terracotta Community Login Required)
Since Hibernate 2.1, Hibernate has included an Ehcache CacheProvider. That provider is periodically synced up with the provider in the Ehcache Core distribution. New features are generally added in to the Ehcache Core provider and then the Hibernate one.
Gavin King and Greg Luck cooperated to create Ehcache and include it in Hibernate. Since 2009 Greg Luck has been a committer on the Hibernate project so as to ensure Ehcache remains a first-class 2nd level cache for Hibernate.
Yes. Ehcache 2.0 supports this new API.
No. JTA support is new in Ehcache 2.0. We plan to add JTA support for Hibernate in an upcoming release at which time we will support this strategy. An exception will be thrown if this strategy is selected.
hibernate.org maintains a table listing the providers. While ehcache works as a distributed cache for Hibernate, it is not listed as "Cluster Safe". What this means is that `Hibernate's lock and unlock methods are not implemented. Changes in one node will be applied without locking. This may or may not be a noticeable problem.
In Ehcache 1.7 when using Terracotta, this cannot happen as access to the clustered cache itself is controlled with read locks and write locks.
In Ehcache 2.0 when using Terracotta, the lock and unlock methods tie-in to the underlying clustered cache locks. We expect Ehcache 2.0 to be marked as cluster safe in new versions of the Hibernate documentation.
Hibernate identifies cached Entities via an object id. This is normally the primary key of a database row.
You cannot use identity mode clustered cache with Hibernate. If the cache is exclusively used by Hibernate we will convert identity mode caches to serialization mode. If the cache cannot be determined to be exclusively used by Hibernate (i.e. generated from a singleton cache manager) then an exception will be thrown indicating the misconfigured cache. Serialization mode is in any case the default for Terracotta clustered caches.
Session.load will always try to use the cache.
Session.find does not use the cache for the primary object. Hibernate will try to use the cache for any associated objects. Session.find does however cause the cache to be populated.
Query.find works in exactly the same way.
Use these where the chance of getting a cache hit is low.
Session.iterate always uses the cache for the primary object and any associated objects.
Query.iterate works in exactly the same way.
Use these where the chance of getting a cache hit is high.
Configuring each Hibernate instance with a standalone ehcache will dramatically improve performance. However most production applications use multiple application instances for redundancy and for scalability. Ideally applications are horizontally scalable, where adding more application instances linearly improves throughput.
With an application deployed on multiple nodes, using standalone Ehcache means that each instance holds its own data. On a cache miss on any node, Hibernate will hit the database. As each new node gets added database workload goes up. The solution is to turn on distributed caching.
Ehcache comes with replicated caching via RMI, JGroups or JMS. These replicate without locking and are suitable for databas offload. Generally session.refresh() should be used to check the cache against the database before performing a write that must be correct. Secondly, as each node stores all data, the cache size is limited to a comfortable storage size. Memory size is usually limited by garbage collection. Disk can also be used, but the graphs are serialized which adds overhead and results in duplication in the deserialized object graphs.
Ehcache is also the caching API to the Terracotta Server Array. Reads and writes use cluster wide locks, so when using read write Hibernate caches, the cache data on all nodes will be correct, and it is not necessary to call session.refresh().
Ehcache EX, using a single or redundant Terracotta Server Array server can comfortably store approximately 20GB per stripe. The maxElementsInMemory cache setting is used to apportion a percentage of that in process for added performance, it does not limit the size. Using striping which comes with Ehcache FX, terabyte sized caches are possible. It is possible to cache the entire database with a resulting large database offload.
These scaling decisions can be deferred. The plugin is the same regardless of how it is configured. The optimal deployment can thus be determined during performance testing or based on production experience. Finally a new application can scale as it's use grows without expensive re-architecting.