2011-05-08 85 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>