2011-05-08 87 views
2

收集Hibernate/Ehcache统计信息并在基于Spring的设置中通过JMX公开它们看起来很容易。互联网有很多资源可以帮助http://snippets.dzone.com/posts/show/11159在Tomcat中通过JMX暴露Hibernate(缓存)统计信息

但是,所有这些文章都假设您正在使用某种Hibernate会话工厂。我不是 - 我的实体是JPA注释,我使用javax.persistence.EntityManager。 如果我正在部署到Java EE容器,我可能已经能够通过JNDI获得Hibernate会话工厂,如此处所述http://internna.blogspot.com/2007/08/hibernate-statistics-in-enterprise-5.html但我在Tomcat上...

如何解决此问题?我还没有提出解决方案。

如果我不得不在了Ehcache CacheManager参考我可以尝试这样的:由于缓存管理器是由Hibernate来创建

<context:mbean-server /> 
<bean class="net.sf.ehcache.management.ManagementService" init-method="init"> 
    <constructor-arg ref="..myCacheManager.."/> 
    <constructor-arg ref="mbeanServer"/> 
    <constructor-arg value="true"/> 
    <constructor-arg value="true"/> 
    <constructor-arg value="true"/> 
    <constructor-arg value="true"/> 
</bean> 

(即它不是一个Spring bean)将无法正常工作。我试图用

<constructor-arg><bean id="cacheManager" class="net.sf.ehcache.CacheManager" factory-method="getInstance"/></constructor-arg> 

希望我能以某种方式捕捉正确的实例。无法正常工作,因为这实际上会创建一个新的缓存管理器实例。

+0

什么的Ehcache版本你正在用吗? 'CacheManager'上没有'getInstance()'方法。 – skaffman 2011-05-09 09:48:10

+0

@skaffman,它在ehcache的核心2.3.1。 – 2011-05-09 20:06:10

回答

1

我最后写了下面的类

HibernateStatisticsJmxRegistration

import javax.management.JMException; 
import javax.management.MBeanServer; 
import javax.management.ObjectName; 
import javax.persistence.EntityManagerFactory; 

import org.hibernate.SessionFactory; 
import org.hibernate.ejb.HibernateEntityManagerFactory; 
import org.hibernate.jmx.StatisticsService; 
import org.springframework.beans.factory.annotation.Autowired; 

/** 
* Provides code to register Hibernate's 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. 
* <p> 
* May become obsolete once <a href="https://hibernate.onjira.com/browse/HHH-6034">HHH-6034</a> is 
* implemented. Even if not the confusing situation abround the meanwhile deprecated 
* {@link StatisticsService} should be clear then. 
*/ 
@SuppressWarnings({"deprecation", "javadoc" }) 
public class HibernateStatisticsJmxRegistration { 

    @Autowired 
    private EntityManagerFactory entityManagerFactory; 

    @Autowired 
    private MBeanServer mbeanServer; 

    private ObjectName objectName; 

    private String jmxObjectName = "org.hibernate:name=HibernateStatistics"; 

    /** 
    * Registers the statistics MBean that wraps a Hibernate session factory. The bean is registered 
    * under the name provided by {@link HibernateStatisticsJmxRegistration#getJmxObjectName()}. 
    * 
    * @throws JMException if anything fails.. 
    * @see HibernateStatisticsJmxRegistration#unregister() 
    */ 
    public void register() throws JMException { 
    final SessionFactory sessionFactory = ((HibernateEntityManagerFactory) entityManagerFactory).getSessionFactory(); 

    objectName = new ObjectName(jmxObjectName); 

    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 HibernateStatisticsJmxRegistration#register() 
    */ 
    public void unregister() throws JMException { 
    mbeanServer.unregisterMBean(objectName); 
    } 

    /** 
    * Override the default JMX object name. Obviously you need to call this method before 
    * registration for it to have any effect. The string must comply to the rules described in 
    * {@link ObjectName}. Suggested is {@code <domain>:name=<name>}. 
    * 
    * @param jmxObjectName the name to use during registration 
    */ 
    public void setJmxObjectName(String jmxObjectName) { 
    this.jmxObjectName = jmxObjectName; 
    } 
} 

Spring配置

<!-- Setting up Ehcache manager for various caches (offer facade, images). --> 
<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="HibernateStatisticsJmxRegistration" 
     init-method="register" destroy-method="unregister" /> 
+0

停止使用Hibernate 4.3.0-Final。请参阅:https://hibernate.atlassian.net/browse/HHH-6190 – 2014-01-14 11:47:01

-1

Spring仅在JMX上公开他的bean,但您可以通过MBeanExporter导出资源。

+0

是的,我知道,但我会尽量避免添加自定义代码只是为了这一点。 – 2011-05-09 20:07:13

+0

你的休眠SessionFactory是一个Spring bean吗? – 2011-05-10 12:31:49

2

的JPA的EntityManager露出下面的Hibernate会话,所以你可以在它的工厂获得:

public static Session getHibernateSession(EntityManager entityManager) { 
     Session session; 
     if (entityManager.getDelegate() instanceof EntityManagerImpl) { 
      EntityManagerImpl entityManagerImpl = (EntityManagerImpl) entityManager.getDelegate(); 
      session = entityManagerImpl.getSession(); 
     } else { 
      session = (Session) entityManager.getDelegate(); 
     } 

     return session; 
    } 

然后可以使用这个会话来enable the statistics就像我们在RHQ project

+0

是的,我可以做到这一点。但理想情况下,它应该以声明的方式完成。 – 2011-05-12 22:04:53

3

干过我已经最近构建了一个基于Spring的示例web应用程序,该应用程序非常干净地为最新版本的Spring,Hibernate和Ehcache启用JMX。

它具有基于EntityManager的访问和DAO访问(包括交易!)的示例。它还显示了如何执行基于注释的注入,以否定必须使用Spring的xml config for beans。甚至有一个基于SpringMVC的示例servlet使用注释。基本上,这是一个在任何servlet引擎上运行的基于Spring的相当强大的应用服务器版本。

目前还没有文件记录,但我很快就会谈到。看看配置文件和源代码,它应该很清楚。

这背后的动机是我厌倦了所有疯狂的博客文章,有50种不同的方式来设置,最后做出了一个简单的来源,人们可以从中工作。它已经在github上了,所以你可以自由地分发项目,并随你做任何你想做的事情。

https://github.com/lookfirst/fallback

+0

-1打扰上传近60个第三方库到github上,什么是资源的浪费。蚂蚁与Maven的的下行建立...检查你的applicationContext.xml,但没有看到它的内容是如何对有关这个问题的? – 2011-05-21 07:59:31

+1

资源浪费?你真的关心别人的磁盘上的几个位?至于我的applicationContext.xml,你正在寻找错误的地方。 https://github.com/lookfirst/fallback/blob/master/src/java/com/github/fallback/util/JmxAgent.java – 2011-05-23 00:39:14

+1

@Marcel如何上传第三方库,以他的github账户影响这个答案的质量?我想我可以倒下评论。 – 2011-07-15 15:12:17

2

实际上,你可以使用公开的任何Spring Expression Language CacheManager的。

<bean id="hibernateCacheManagement" class="net.sf.ehcache.management.ManagementService" init-method="init" > 
    <constructor-arg value="#{T(net.sf.ehcache.CacheManager).getCacheManager('CACHE_NAME')}"/> 
    <constructor-arg><ref bean="mbeanServer"/></constructor-arg> 
    <constructor-arg value="true"/> 
    <constructor-arg value="true"/> 
    <constructor-arg value="true"/> 
    <constructor-arg value="true"/> 
</bean> 

其中CACHE_NAME是在ehcache.xml文件中配置的缓存的名称。

<ehcache name="CACHE_NAME"> 
    ... 
</ehcache> 
0

非常哎哟,但这个工程,太,在这里(猜测)的MBeanServer是MBean服务器的bean的名字和entityManagerFactory的是EntityManagerFactory的bean的名称:

<bean id="managementService-ehcache-hibernate" 
    class="net.sf.ehcache.management.ManagementService" 
    init-method="init" 
    destroy-method="dispose"> 

    <constructor-arg value="#{T(org.springframework.security.util.FieldUtils).getFieldValue(@entityManagerFactory.cache.unwrap(T(org.hibernate.cache.spi.RegionFactory)),'manager')}"/> 
    <constructor-arg ref="mbeanServer"/> 
    <constructor-arg index="2" value="true"/> 
    <constructor-arg index="3" value="true"/> 
    <constructor-arg index="4" value="true"/> 
    <constructor-arg index="5" value="true"/> 
</bean>