Site icon Voina Blog (a tech warrior's blog)

Activate #infinispan second level cache with #jboss and #hibernate

Advertisements

Second level cache is an extremely powerful way to improve performance of an enterprise application if done right.

In the following I will explain how to activate and configure second level cache when using Hibernate and Jboss 7.4+ application server.

Jboss 7.4 comes with Infinispan as the build in second level cache solution. This makes it very easy to use and configure. You can get read of the library compatibility issues you can have while using other cache engines like EhCache where you must match the right version to your Jboss application server version.

By default Jboss 7.4+ comes with infinispan module activated and configured. No other libraries have to be installed or dependencies in your code.

We assume that the enterprise application persistence layer using Hibernate is configured using persistance.xml configuration file.

To activate infinispan as a second level cache you just need to add at the data source definition the following:

<persistence-unit name="default" transaction-type="JTA">
	<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
	<jta-data-source>jboss/datasources/MyDS</jta-data-source>
...
<properties>
	<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect" />
	<property name="hibernate.hbm2ddl.auto" value="update" />
	<!--  Infinispan second level cache start -->
	<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.JndiInfinispanRegionFactory" />
        <property name="hibernate.cache.use_second_level_cache" value="true" />
	<property name="hibernate.cache.use_query_cache" value="true" />
	<property name="hibernate.cache.use_structured_cache" value="no" />
...
</properties>

where:

We may add some additional properties to change the default parameters.

        <property name="hibernate.cache.infinispan.statistics" value="false"/>
	<property name="hibernate.cache.infinispan.entity.eviction.strategy" value= "LRU"/>
	<property name="hibernate.cache.infinispan.entity.eviction.wake_up_interval" value= "2000"/>
	<property name="hibernate.cache.infinispan.entity.eviction.max_entries" value= "5000"/>
	<property name="hibernate.cache.infinispan.entity.expiration.lifespan" value= "60000"/>
	<property name="hibernate.cache.infinispan.entity.expiration.max_idle" value= "30000"/>

where:

Of course this is not enough we must add some additional properties to control what is cached and how.

For caching entities the following configuration has to be added for each entity from our application that needs to be cached.

        <property name="hibernate.ejb.classcache.org.voina.core.MyEntity" value="read-write"/>
	<property name="hibernate.ejb.collectioncache.org.voina.core.MyEntity.collection" value="read-write"/>

where:

For a query to be cache-able the following must be done:

When a query is defined inline in the code the hint can be given as:

entityManager.createQuery("select f from Foo f")
  .setHint("org.hibernate.cacheable", true)
  .getResultList();

When the query is defined as a named query in a separate query file:

<?xml version="1.0" encoding="UTF-8"?>
<orm:entity-mappings version="1.0" xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm  
	http://java.sun.com/xml/ns/persistence/orm_1_0.xsd">

	<orm:named-query name="findFoo">
		<orm:query>
			select f from Foo f
		<orm:hint name="org.hibernate.cacheable" value="true" />
	</orm:named-query>
...	

To check if you need to cache a query or entity before the cache activation and after cache activation you should use you database of choice tools to find out queries that have a high number of executions and return static or qvasi-static data. For Oracle a good guide is https://blog.voina.fr/oracle-quick-way-to-investigate-slow-or-time-consuming-application-queries/

Exit mobile version