Question

I'm using Spring 3.1.1.RELEASE, JUnit 4.8.1, and Hibernate 4.1.5.Final. I'm trying to test whether my second level cache is configured correctly, but am unsure of how to do it. I'm using the JPA entity manager, configured in Spring like so ...

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaDialect">
        <bean class="org.collegeboard.springboard.core.jpa.HibernateJpaDialect">
            <property name="flushMode" value="COMMIT"/>
        </bean>
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
    <property name="persistenceXmlLocation" value="classpath:META-INF/test-persistence.xml"/>
    <property name="persistenceUnitName" value="orgTestingDatabase"/>
    <property name="dataSource" ref="dataSource"/>
</bean>

<bean id="sharedEntityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
   <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

I have configured my second level cache like so ...

    <property name="hibernate.cache.use_second_level_cache">true</property>
    <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
    <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> 
    <!--  Collect stats, this is for testing if the cache is working -->
    <property name="hibernate.generate_statistics">true</property>

How do I access a org.hibernate.stat.Statistics object given my javax.persistence.EntityManager ? Evidently, I need to access a SessionFactory somehow, but I can't figure out the appropriate series of casts.

Thanks, - Dave

Was it helpful?

Solution

I was wrestling with this in the past: Exposing Hibernate (cache) statistics through JMX with Spring in Tomcat

If you simply want to know "if it's working" you could enable Hibernate debug logging for org.hibernate.stat.Statistics or org.hibernate.stat.*. However, if you (like I) want to have a cache statistics report you could do something like the following. This exposes a JMX bean with all the stats:

/**
 * Provides code to register Hibernate's 2nd level cache statistics bean with a
 * JMX MBean server. Assumes that both the MBeanServer and the
 * EntityManagerFactory are available as Spring-managed beans. Note that while
 * registering this class enables the collection of statistics even if that was
 * previously disabled.
 */
public class HibernateCacheStatisticsJmxRegistration {

  @Autowired
  private EntityManagerFactory entityManagerFactory;

  @Autowired
  private MBeanServer mbeanServer;

  private ObjectName objectName;

  /**
   * Registers the statistics MBean that wraps a Hibernate session factory.
   * 
   * @throws JMException if anything fails..
   * @see HibernateCacheStatisticsJmxRegistration#unregister()
   */
  public void register() throws JMException {
    final SessionFactory sessionFactory = ((HibernateEntityManagerFactory) entityManagerFactory).getSessionFactory();

    objectName = new ObjectName("net.sf.ehcache:type=CacheStatistics,name=Hibernate2ndLevelCache");

    final StatisticsService statsMBean = new StatisticsService();
    statsMBean.setSessionFactory(sessionFactory);
    statsMBean.setStatisticsEnabled(true);
    mbeanServer.registerMBean(statsMBean, objectName);
  }

  /**
   * Unregisters the MBean that was registered.
   * 
   * @throws JMException if the de-registration fails
   * @see HibernateCacheStatisticsJmxRegistration#register()
   */
  public void unregister() throws JMException {
    mbeanServer.unregisterMBean(objectName);
  }
}

The app context:

<!-- Setting up Ehcache manager for various caches. -->
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
  <property name="configLocation" value="classpath:ehcache.xml" />
</bean>  
<ehcache:annotation-driven cache-manager="ehCacheManager" />

<!-- Exposing cache statistics through JMX. -->
<context:mbean-server />
<bean class="net.sf.ehcache.management.ManagementService" init-method="init">
  <constructor-arg ref="ehCacheManager"/>
  <constructor-arg ref="mbeanServer"/>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
  <constructor-arg value="true"/>
</bean>    
<bean class="HibernateCacheStatisticsJmxRegistration" init-method="register" destroy-method="unregister" />

OTHER TIPS

Entity manager has a method called getDelegate. Call this and type cast it to hibernate session object. Once you have hibernate session object you can get the session factory and statistics.

There are multiple ways you can access the Hibernate Statistics:

Programmatically

If you want to get the Statistics object in your application, you can do it as follows:

Session session = entityManager.unwrap(Session.class);

Statistics statistics = session.getSessionFactory().getStatistics();

First, we unwrapped the EntityManager to the Hibernate Session, and then you can access the Syatistics via the associated SesisonFactory.

Logging

If can also log the Statistics report, in which case, you need to add the following log configuration entry:

<logger name="org.hibernate.engine.internal.StatisticalLoggingSessionEventListener" level="info"/>

JMX

For Hibernate 5.4.2 and later, you can also expose the Statistics object via JMX.

For this, you need to set the hibernate.jmx.enabled configuration property:

<property name="hibernate.jmx.enabled" value="true"/>

And locate the org.hibernate.core MBean package in your JMX client application.

Easiest way is to define a bean for your SessionFactory and just Autowire it in. There's no direct way to get the SessionFactory from the EntityManager, as far as I'm aware.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top