JBoss.org Community Documentation

16.2.3. Query result caching

The EJB3 Query API also provides means for you to save in the second-level cache the results (i.e., collections of primary keys of entity beans, or collections of scalar values) of specified queries. Here we show a simple example of annotating a bean with a named query, also providing the Hibernate-specific hints that tells Hibernate to cache the query.

First, in persistence.xml you need to tell Hibernate to enable query caching:

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

Next, you create a named query associated with an entity, and tell Hibernate you want to cache the results of that query:

 
@Entity
@Cache (usage=CacheConcurrencyStrategy.TRANSACTIONAL,
region=”Account”)
@NamedQueries({
@NamedQuery(name="account.bybranch",
query="select acct from Account as acct where acct.branch = ?1",
hints={@QueryHint(name="org.hibernate.cacheable",value="true")})           
})
public class Account implements Serializable { 
// ... ... 
}

The @NamedQueries, @NamedQuery and @QueryHint annotations are all in the javax.persistence package.See the Hibernate and EJB3 documentation for more on how to use EJB3 queries and on how to instruct EJB3 to cache queries.

By default, Hibernate stores query results in JBoss Cache in a region named {region_prefix}/org/hibernate/cache/StandardQueryCache. Based on this, you can set up separate eviction handling for your query results. So, if the region prefix were set to myprefix in persistence.xml, you could, for example, create this sort of eviction handling:

 
<server>  
	  <mbean code="org.jboss.cache.TreeCache" 
		 name="jboss.cache:service=EJB3EntityTreeCache">
		  ... ... 
		  <attribute name="EvictionPolicyConfig">  
			  <config>  
			  <attribute name="wakeUpIntervalSeconds">5</attribute>  
				  <region name="/_default_">  
				  <attribute name="maxNodes">5000</attribute>  
				  <attribute name="timeToLiveSeconds">1000</attribute>  
				  </region>  
				  <!-- Separate eviction rules for Account entities -->
				  <region name="/myprefix/Account">  
					  <attribute name="maxNodes">10000</attribute>  
					  <attribute name="timeToLiveSeconds">5000</attribute>  
				  </region>
				  <!-- Cache queries for 10 minutes -->
				  <region name="/myprefix/org/hibernate/cache/StandardQueryCache">  
					  <attribute name="maxNodes">100</attribute>  
					  <attribute name="timeToLiveSeconds">600</attribute>  
				  </region>  
				  ... ... 
			  </config>  
		  </attribute>  
	  </mbean> 
</server>
	  

The @NamedQuery.hints attribute shown above takes an array of vendor-specific @QueryHints as a value. Hibernate accepts the “org.hibernate.cacheRegion” query hint, where the value is the name of a cache region to use instead ofthe default /org/hibernate/cache/StandardQueryCache. For example:

	@Entity
	@Cache (usage=CacheConcurrencyStrategy.TRANSACTIONAL,
	region=”Account”)
	@NamedQueries({
	@NamedQuery(name="account.bybranch",
	query="select acct from Account as acct where acct.branch = ?1",
	hints={@QueryHint(name="org.hibernate.cacheable",value="true"),
	@QueryHint(name=”org.hibernate.cacheRegion,value=”Queries”)
	})           
	})
	public class Account implements Serializable { 
	// ... ... 
	}

The related eviction configuration:

	
<server>  
	<mbean code="org.jboss.cache.TreeCache" 
	       name="jboss.cache:service=EJB3EntityTreeCache">
		... ... 
		<attribute name="EvictionPolicyConfig">  
			<config>  
				<attribute name="wakeUpIntervalSeconds">5</attribute>  
				<region name="/_default_">  
					<attribute name="maxNodes">5000</attribute>  
					<attribute name="timeToLiveSeconds">1000</attribute>  
				</region>  
				<!-- Separate eviction rules for Account entities -->
				<region name="/myprefix/Account">  
					<attribute name="maxNodes">10000</attribute>  
					<attribute name="timeToLiveSeconds">5000</attribute>  
				</region>
				<!-- Cache queries for 10 minutes -->
				<region name="/myprefix/Queries">  
					<attribute name="maxNodes">100</attribute>  
					<attribute name="timeToLiveSeconds">600</attribute>  
				</region>  
				... ... 
			</config>  
		</attribute>  
	</mbean> 
</server>