Kohei Nozaki's blog 

Just try to use 2nd level cache with WildFly and Hibernate


Posted on Wednesday Feb 19, 2014 at 05:30PM in Technology


Just playing with 2nd level cache that mentioned at [1]. it is a good tutorial so may we only need to refer [1], and this is my notes and logs only.

Environment

  • WildFly 8.0.0.Final (Hibernate 4.3.1)
  • Maven 3.1.1
  • Oracle JDK7u51
  • OS X 10.9.1

Run Maven to get the sample project

kyle-no-MacBook:l2cache kyle$ mvn archetype:generate \
>     -DarchetypeArtifactId=jboss-javaee6-webapp-archetype \
>     -DarchetypeGroupId=org.jboss.spec.archetypes \
>     -DarchetypeVersion=7.1.2.Final \
>     -DgroupId=de.consol.research \
>     -DartifactId=infinispan-jpa-example \
>     -Dversion=1.0-SNAPSHOT \
>     -Dname="Infinispan JPA Example" \
>     -DarchetypeCatalog=http://search.maven.org/remotecontent?filepath=archetype-catalog.xml \
>     -DinteractiveMode=false
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
[INFO] Scanning for projects...
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-install-plugin/2.4/maven-install-plugin-2.4.pom
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-install-plugin/2.4/maven-install-plugin-2.4.pom (7 KB at 5.4 KB/sec)
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-deploy-plugin/2.7/maven-deploy-plugin-2.7.pom
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-deploy-plugin/2.7/maven-deploy-plugin-2.7.pom (6 KB at 20.5 KB/sec)
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-site-plugin/3.3/maven-site-plugin-3.3.pom
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-site-plugin/3.3/maven-site-plugin-3.3.pom (21 KB at 51.1 KB/sec)
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-site-plugin/3.3/maven-site-plugin-3.3.jar
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-site-plugin/3.3/maven-site-plugin-3.3.jar (122 KB at 180.7 KB/sec)
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-antrun-plugin/1.3/maven-antrun-plugin-1.3.pom
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-antrun-plugin/1.3/maven-antrun-plugin-1.3.pom (5 KB at 17.0 KB/sec)
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-antrun-plugin/1.3/maven-antrun-plugin-1.3.jar
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-antrun-plugin/1.3/maven-antrun-plugin-1.3.jar (24 KB at 84.3 KB/sec)
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-assembly-plugin/2.2-beta-5/maven-assembly-plugin-2.2-beta-5.pom
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-assembly-plugin/2.2-beta-5/maven-assembly-plugin-2.2-beta-5.pom (15 KB at 55.4 KB/sec)
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-plugins/16/maven-plugins-16.pom
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-plugins/16/maven-plugins-16.pom (13 KB at 47.0 KB/sec)
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-assembly-plugin/2.2-beta-5/maven-assembly-plugin-2.2-beta-5.jar
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-assembly-plugin/2.2-beta-5/maven-assembly-plugin-2.2-beta-5.jar (204 KB at 357.8 KB/sec)
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-dependency-plugin/2.8/maven-dependency-plugin-2.8.pom
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-dependency-plugin/2.8/maven-dependency-plugin-2.8.pom (12 KB at 41.7 KB/sec)
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-dependency-plugin/2.8/maven-dependency-plugin-2.8.jar
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-dependency-plugin/2.8/maven-dependency-plugin-2.8.jar (150 KB at 274.5 KB/sec)
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom >>>
[INFO] 
[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom <<<
[INFO] 
[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom ---
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/reporting/maven-reporting-api/2.0.8/maven-reporting-api-2.0.8.jar
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/doxia/doxia-sink-api/1.0-alpha-9/doxia-sink-api-1.0-alpha-9.jar
Downloading: http://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-interactivity-api/1.0-alpha-5/plexus-interactivity-api-1.0-alpha-5.jar
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/reporting/maven-reporting-api/2.0.8/maven-reporting-api-2.0.8.jar (10 KB at 28.5 KB/sec)
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/doxia/doxia-sink-api/1.0-alpha-9/doxia-sink-api-1.0-alpha-9.jar (10 KB at 19.8 KB/sec)
Downloaded: http://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-interactivity-api/1.0-alpha-5/plexus-interactivity-api-1.0-alpha-5.jar (14 KB at 26.0 KB/sec)
[INFO] Generating project in Batch mode
[INFO] Archetype repository missing. Using the one from [org.jboss.spec.archetypes:jboss-javaee6-webapp-archetype:7.1.3.Final] found in catalog http://search.maven.org/remotecontent?filepath=archetype-catalog.xml
Downloading: http://search.maven.org/org/jboss/spec/archetypes/jboss-javaee6-webapp-archetype/7.1.2.Final/jboss-javaee6-webapp-archetype-7.1.2.Final.jar
Downloading: http://repo.maven.apache.org/maven2/org/jboss/spec/archetypes/jboss-javaee6-webapp-archetype/7.1.2.Final/jboss-javaee6-webapp-archetype-7.1.2.Final.jar
Downloaded: http://repo.maven.apache.org/maven2/org/jboss/spec/archetypes/jboss-javaee6-webapp-archetype/7.1.2.Final/jboss-javaee6-webapp-archetype-7.1.2.Final.jar (96 KB at 88.0 KB/sec)
Downloading: http://search.maven.org/org/jboss/spec/archetypes/jboss-javaee6-webapp-archetype/7.1.2.Final/jboss-javaee6-webapp-archetype-7.1.2.Final.pom
Downloading: http://repo.maven.apache.org/maven2/org/jboss/spec/archetypes/jboss-javaee6-webapp-archetype/7.1.2.Final/jboss-javaee6-webapp-archetype-7.1.2.Final.pom
Downloaded: http://repo.maven.apache.org/maven2/org/jboss/spec/archetypes/jboss-javaee6-webapp-archetype/7.1.2.Final/jboss-javaee6-webapp-archetype-7.1.2.Final.pom (3 KB at 5.5 KB/sec)
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: jboss-javaee6-webapp-archetype:7.1.2.Final
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: de.consol.research
[INFO] Parameter: artifactId, Value: infinispan-jpa-example
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: de.consol.research
[INFO] Parameter: packageInPathFormat, Value: de/consol/research
[INFO] Parameter: package, Value: de.consol.research
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: name, Value: Infinispan JPA Example
[INFO] Parameter: groupId, Value: de.consol.research
[INFO] Parameter: jboss-bom-enterprise-version, Value: 1.0.4.Final-redhat-1
[INFO] Parameter: artifactId, Value: infinispan-jpa-example
[INFO] Parameter: enterprise, Value: false
[INFO] project created from Archetype in dir: /Users/kyle/src/l2cache/infinispan-jpa-example
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 18.514s
[INFO] Finished at: Wed Feb 19 17:26:26 JST 2014
[INFO] Final Memory: 14M/245M
[INFO] ------------------------------------------------------------------------

Import the project to Eclipse

  • File - Import - Existing Maven Projects
  • It comes with no errors.

Make the application to use PostgreSQL

This is not necessary for everyone. It comes with internal H2 datasource definition in the application so we can just skip this work.

Create a database

jbatch=# create database infinispan owner kyle encoding 'UTF8' TEMPLATE template0;
CREATE DATABASE
jbatch=# 

Define a data source

data-source add \
 --name=InfinispanExampleDS \
 --driver-name=postgresql \
 --connection-url=jdbc:postgresql://localhost:5432/infinispan \
 --jndi-name=java:jboss/datasources/infinispan-jpa-exampleDS \
 --user-name=postgres \
 --password=***

Delete datasource definition in WEB-INF

delete Deployed Resources/webapp/WEB-INF/infinispan-jpa-example-ds.xml

Deploy

I did it with Eclipse.

  1. Open Servers Window
  2. Right-click WildFly
  3. Add and remove
  4. Add infinispan-jpa-example
  5. Finish

Browse JSF page

  • Browse here
  • When we reload the page, every time it executes SELECT clause. like this:
17:46:37,631 DEBUG [org.hibernate.SQL] (default task-11) select member0_.id as id1_0_, member0_.email as email2_0_, member0_.name as name3_0_, member0_.phone_number as phone_nu4_0_ from Member member0_ order by member0_.name asc
17:46:39,055 DEBUG [org.hibernate.SQL] (default task-12) select member0_.id as id1_0_, member0_.email as email2_0_, member0_.name as name3_0_, member0_.phone_number as phone_nu4_0_ from Member member0_ order by member0_.name asc
17:49:13,527 DEBUG [org.hibernate.SQL] (default task-10) select member0_.id as id1_0_, member0_.email as email2_0_, member0_.name as name3_0_, member0_.phone_number as phone_nu4_0_ from Member member0_ order by member0_.name asc
  • One test data is already registered when we browse the page.

Send GET request

kyle-no-MacBook:infinispan-jpa-example kyle$ curl http://localhost:8080/infinispan-jpa-example/rest/members/0 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><member><email>john.smith@mailinator.com</email><id>0</id><name>John Smith</name><phoneNumber>2125551212</phoneNumber></member>kyle-no-MacBook:infinispan-jpa-example kyle$ 

It executes SQL for every request.

17:55:28,664 DEBUG [org.hibernate.SQL] (default task-6) select member0_.id as id1_0_0_, member0_.email as email2_0_0_, member0_.name as name3_0_0_, member0_.phone_number as phone_nu4_0_0_ from Member member0_ where member0_.id=?
17:55:28,665 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] (default task-6) binding parameter [1] as [BIGINT] - [0]

Modify persistence.xml to use l2-cache

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
   xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="primary">
      <!-- If you are running in a production environment, add a managed 
         data source, the example data source is just for development and testing! -->
      <jta-data-source>java:jboss/datasources/infinispan-jpa-exampleDS</jta-data-source>
      <shared-cache-mode>DISABLE_SELECTIVE</shared-cache-mode>
      <properties>
         <!-- Properties for Hibernate -->
         <property name="hibernate.hbm2ddl.auto" value="create-drop" />
         <property name="hibernate.show_sql" value="false" />
         <property name="hibernate.cache.use_second_level_cache" value="true"/>
      </properties>
   </persistence-unit>
</persistence>

Send GET request again

  • Now SQL is executed only once.

Browse JSF page again

  • It still executes SQL every time I reload. why?

Make the application to allow to use l2-cache for queries

In reference to [2], we still have to modify some codes.

Modify persistence.xml

Add this property:

         <property name="hibernate.cache.use_query_cache" value="true" />

Now it is:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
   xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="primary">
      <!-- If you are running in a production environment, add a managed 
         data source, the example data source is just for development and testing! -->
      <jta-data-source>java:jboss/datasources/infinispan-jpa-exampleDS</jta-data-source>
      <shared-cache-mode>DISABLE_SELECTIVE</shared-cache-mode>
      <properties>
         <!-- Properties for Hibernate -->
         <property name="hibernate.hbm2ddl.auto" value="create-drop" />
         <property name="hibernate.show_sql" value="false" />
         <property name="hibernate.cache.use_second_level_cache" value="true"/>
         <property name="hibernate.cache.use_query_cache" value="true" />
      </properties>
   </persistence-unit>
</persistence>

Modify the code of JSF page

The query is executed in MemberListProducer#retrieveAllMembersOrderedByName():

   @PostConstruct
   public void retrieveAllMembersOrderedByName() {
      CriteriaBuilder cb = em.getCriteriaBuilder();
      CriteriaQuery<Member> criteria = cb.createQuery(Member.class);
      Root<Member> member = criteria.from(Member.class);
      // Swap criteria statements if you would like to try out type-safe criteria queries, a new
      // feature in JPA 2.0
      // criteria.select(member).orderBy(cb.asc(member.get(Member_.name)));
      criteria.select(member).orderBy(cb.asc(member.get("name")));
      members = em.createQuery(criteria).getResultList();
   }

Add the code that invokes Query#setHint():

setHint("org.hibernate.cacheable", true)

Now the code is:

   @PostConstruct
   public void retrieveAllMembersOrderedByName() {
       CriteriaBuilder cb = em.getCriteriaBuilder();
       CriteriaQuery<Member> criteria = cb.createQuery(Member.class);
       Root<Member> member = criteria.from(Member.class);
       // Swap criteria statements if you would like to try out type-safe criteria queries, a new
       // feature in JPA 2.0
       // criteria.select(member).orderBy(cb.asc(member.get(Member_.name)));
       criteria.select(member).orderBy(cb.asc(member.get("name")));
       members = em.createQuery(criteria).setHint("org.hibernate.cacheable", true).getResultList();
   }

Browse JSF page once again

  • Now SQL is executed only once even I reloaded many times.

Remarks

  • As default, 2nd level cache is disabled for queries.
    • It seems enabled for operations like EntityManager#find() only.
    • Every time queries need to set hint “org.hibernate.cacheable=true”.
  • According to [3], it seems to there is a way to avoid to invoke annoying setHint() method for every queries.
    • Seems to Query Hints are can define at when we declare Named Query.
    • May I would try it later.

References

  1. Infinispan JPA 2nd Level Caching on JBoss AS 7 – Minimal Working Example – ConSol* Labs
  2. JPAのSecond Level Cacheを試してみる - Starlight
  3. 4.2.3. Query result caching