问题
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
回答1:
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" />
回答2:
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.
回答3:
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, as explained in this article.
For this, you need to set the following configuration property:
<property name="hibernate.jmx.enabled" value="true"/>
And locate the org.hibernate.core
MBean package in your JMX client application.
If you want to get a better idea of what metrics Hibernate supports, then check out this article.
回答4:
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.
来源:https://stackoverflow.com/questions/14106575/how-do-i-access-hibernate-statistics-from-an-entitymanager