This site hosts historical documentation. Visit www.terracotta.org for recent product information.
Big Memory Go easily integrates with the Hibernate Object/Relational persistence and query service. To configure BigMemory Go for Hibernate:
ehcache.xml
file as necessary for each entity, collection, or
query configured for caching.For more information about cache configuration in Hibernate, see the Hibernate documentation.
The Hibernate provider is in the ehcache-ee module provided in the BigMemory Go kit.
Dependency versions vary, depending on which kit you use. Each kits is guaranteed to contain compatible artifacts, so find the artifact versions you need by downloading a kit. Configure or add the following repository to your build (pom.xml):
<repository>
<id>terracotta-releases</id>
<url>http://www.terracotta.org/download/reflector/releases</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository>
Configure or add the Ehcache and BigMemory modules defined by the following dependency to your build (pom.xml):
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-ee</artifactId>
<version>${ehcacheVersion}</version>
</dependency>
<dependency>
<groupId>org.terracotta.bigmemory</groupId>
<artifactId>bigmemory</artifactId>
<version>${bigmemoryVersion}</version>
</dependency>
For the Hibernate-Ehcache integration, add the following dependency:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>${hibernateVersion}</version>
</dependency>
For example, the Hibernate-Ehcache integration dependency for Hibernate 4.0.0 is:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>4.0.0</version>
</dependency>
NOTE: Some versions of hibernate-ehcache might have a dependency on a specific version of Ehcache. Check the hibernate-ehcache POM.
To configure BigMemory Go as a Hibernate second-level cache, set the region factory property to one of the following in the Hibernate configuration. Hibernate configuration is configured either by hibernate.cfg.xml, hibernate.properties, or Spring. The format given is for hibernate.cfg.xml.
For instance creation:
<property name="hibernate.cache.region.factory_class">
net.sf.ehcache.hibernate.EhCacheRegionFactory</property>
To force Hibernate to use a singleton of Ehcache CacheManager:
<property name="hibernate.cache.region.factory_class">
net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory</property>
For Hibernate 4, use org.hibernate.cache.ehcache.EhCacheRegionFactory
instead of net.sf.ehcache.hibernate.EhCacheRegionFactory
, or org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
instead of net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory
.
In addition to configuring the second-level cache provider setting, turn on the second-level cache (by default it is configured to off - "false" - by Hibernate). This is done by setting the following property in your hibernate config:
<property name="hibernate.cache.use_second_level_cache">true</property>
You might also want to turn on the Hibernate query cache. This is done by setting the following property in your hibernate config:
<property name="hibernate.cache.use_query_cache">true</property>
The following settings or actions are optional.
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.
The resource is searched for in the root of the classpath. It is used
to support multiple CacheManagers in the same JVM. 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.
net.sf.ehcache.configurationResourceName=/name_of_ehcache.xml
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")
For Hibernate 4, use org.hibernate.cache.ehcache.EhCacheRegionFactory
instead of net.sf.ehcache.hibernate.EhCacheRegionFactory
.
If you are enabling both second-level caching and query caching, your hibernate config file should contain the following:
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.region.factory_class">
net.sf.ehcache.hibernate.EhCacheRegionFactory</property>
An equivalent Spring configuration file would contain:
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">
net.sf.ehcache.hibernate.EhCacheRegionFactory</prop>
For Hibernate 4, use org.hibernate.cache.ehcache.EhCacheRegionFactory
instead of net.sf.ehcache.hibernate.EhCacheRegionFactory
.
In addition to configuring the Hibernate second-level cache provider, Hibernate must also be configure to enable caching for entities, collections, and queries. For example, to enable cache entries for the domain object com.somecompany.someproject.domain.Country, there would be a mapping file similar to the following:
<hibernate-mapping>
<class
name="com.somecompany.someproject.domain.Country"
table="ut_Countries"
dynamic-update="false"
dynamic-insert="false"
>
...
</class>
</hibernate-mapping>
To enable caching, add the following element.
<cache usage="read-write|nonstrict-read-write|read-only" />
For example:
<hibernate-mapping>
<class
name="com.somecompany.someproject.domain.Country"
table="ut_Countries"
dynamic-update="false"
dynamic-insert="false"
>
<cache usage="read-write" />
...
</class>
</hibernate-mapping>
This can also be achieved using the @Cache annotation, e.g.
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Country {
...
}
Caches data that is never updated.
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!
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.
Because the ehcache.xml
file has a defaultCache, caches are 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 maxEntriesLocalHeap and specifying whether to swap to disk 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. For example, to create a cache for com.somecompany.someproject.domain.Country, create a cache configuration entry in ehcache.xml similar to the following.
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<cache
name="com.somecompany.someproject.domain.Country"
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
<persistence strategy="localTempSwap"/>
/>
</ehcache>
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:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<cache name="com.somecompany.someproject.domain.Country"
maxEntriesLocalHeap="50"
eternal="false"
timeToLiveSeconds="600"
<persistence strategy="localTempSwap"/>
/>
<cache
name="com.somecompany.someproject.domain.Country.advancedSearchFacilities"
maxEntriesLocalHeap="450"
eternal="false"
timeToLiveSeconds="600"
<persistence strategy="localTempSwap"/>
/>
</ehcache>
read-write, nonstrict-read-write and read-only policies apply to Domain Object collections.
Hibernate allows the caching of query results using two caches.
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"
maxEntriesLocalHeap="5"
eternal="false"
timeToLiveSeconds="120"
<persistence strategy="localTempSwap"/>
/>
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. Therefore, 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"
maxEntriesLocalHeap="5000"
eternal="true"
<persistence strategy="localTempSwap"/>
/>
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 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. For example:
<cache name="query.AdministrativeAreasPerCountry"
maxEntriesLocalHeap="5"
eternal="false"
timeToLiveSeconds="86400"
<persistence strategy="localTempSwap"/>
/>
Suppose we have a common query running against the Country Domain. The 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.
Alex Miller has an article on 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 a demo application showing how to use the Hibernate CacheRegionFactory.
Check out from the Terracotta Forge.
Session.load
always tries to use the cache.
Session.find
does not use the cache for the primary object. Hibernate
tries 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.
While you could share the resource file between the two CacheManagers, a clear separation between the two is recommended. Your application might have a different lifecycle than Hibernate, and in each case your CacheManager Automatic Resource Control (ARC) settings might need to be different.
Starting with Hibernate 2.1, Hibernate has included an Ehcache CacheProvider
. That provider
is periodically put in synch with the provider in the Ehcache Core distribution. New
features are generally added in to the Ehcache Core provider and then the Hibernate one.
Yes. It was introduced in Ehcache 2.1.
Whenever a Query.executeUpdate()
is run, for example, Hibernate invalidates affected cache regions (those corresponding to affected database tables) to ensure that no stale data is cached. This should also happen whenever stored procedures are executed.
For more information, see this Hibernate bug report.
Hibernate identifies cached Entities by an object id. This is normally the primary key of a database row.
Yes.
Soft locks are implemented by replacing a value with a special type that marks the element as locked, thus indicating to other threads to treat it differently to a normal element. This is used in the Hibernate Read/Write strategy to force fall-through to the database during the two-phase commit. We cannot know exactly what should be returned by the cache while the commit is in process (but the database does). If a soft-locked Element is evicted by the cache during the two-phase commit, after the two-phase commit completes, the cache will fail to update (because the soft-locked Element was evicted) and the cache entry will be reloaded from the database on the next read of that object. This is non-fatal, but could slightly increase the database load.
In summary, the Hibernate messages are not problematic.
The underlying cause is the probabilistic evictor can theoretically evict recently loaded items. You can also use the deterministic evictor to avoid this problem. Specify the java -Dnet.sf.ehcache.use.classic.lru=true
system property to turn on classic LRU which contains a deterministic evictor.