2012-06-02 62 views
10

我使用Spring框架3.1與Hibernate 4.1作爲JPA提供者,和我擁有全面的功能設置,但每一個Web應用程序啓動時,我看到這個警告消息:春3.1 + Hibernate的JPA 4.1,實體管理器工廠被註冊了兩次

14:28:12,725 WARN pool-2-thread-12 internal.EntityManagerFactoryRegistry:80 - HHH000436: Entity manager factory name (something) is already registered. If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name' 

應用功能就好了,但這樣的打擾我警告消息,並且搜索和調整和試驗的時間都使我無處。我試着改變工廠名稱添加和省略的配置塊,都無濟於事。看來Spring或Hibernate中的某些東西只是初始化實體管理器工廠兩次。

僅供參考,我使用的LocalContainerEntityManagerFactoryBean的packagesToScan功能配置實體管理器,而不persistence.xml文件。

我相比下來我的Spring上下文XML以下和問題仍然存在:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xsi:schemaLocation=" 
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 

    <context:property-placeholder location="classpath:jdbc.properties"/> 
    <bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close"> 
    <property name="driverClassName" value="${jdbc.nightsword.driverClassName}"/> 
    <property name="url" value="${jdbc.nightsword.url}"/> 
    <property name="username" value="${jdbc.nightsword.username}"/> 
    <property name="password" value="${jdbc.nightsword.password}"/> 
    </bean> 

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> 
    </property> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="packagesToScan" value="x.y"/> 
    </bean> 
</beans> 

爲了完整起見,這裏的hibernate.properties:

hibernate.dialect=org.hibernate.dialect.MySQL5Dialect 
hibernate.ejb.entitymanager_factory_name=something 

,這裏是摘錄的調試級別的日誌來自org.springframework.orm和org.hibernate的輸出。你可以看到如何在14:40:06911 EntityManagerFactory是從第一次註冊,此後立即LocalContainerEntityManagerFactoryBean似乎從一開始就從頭開始。呵呵。

INFO: Deploying web application archive /opt/local/share/java/tomcat7/webapps/nightsword.war 
14:40:06,149 INFO pool-2-thread-13 jpa.LocalContainerEntityManagerFactoryBean:264 - Building JPA container EntityManagerFactory for persistence unit 'default' 
14:40:06,219 DEBUG pool-2-thread-13 type.BasicTypeRegistry:143 - Adding type registration boolean -> [email protected] 

... 

14:40:06,882 DEBUG pool-2-thread-13 internal.SessionFactoryRegistry:62 - Initializing SessionFactoryRegistry : [email protected] 
14:40:06,882 DEBUG pool-2-thread-13 internal.SessionFactoryRegistry:75 - Registering SessionFactory: a3219dd8-7d59-45ac-9a5a-0d13e38dbb04 (<unnamed>) 
14:40:06,882 DEBUG pool-2-thread-13 internal.SessionFactoryRegistry:82 - Not binding SessionFactory to JNDI, no JNDI name configured 
14:40:06,882 DEBUG pool-2-thread-13 internal.SessionFactoryImpl:487 - Instantiated session factory 
14:40:06,882 DEBUG pool-2-thread-13 internal.SessionFactoryImpl:1119 - Checking 0 named HQL queries 
14:40:06,883 DEBUG pool-2-thread-13 internal.SessionFactoryImpl:1142 - Checking 0 named SQL queries 
14:40:06,887 DEBUG pool-2-thread-13 internal.StatisticsInitiator:110 - Statistics initialized [enabled=false] 
14:40:06,910 DEBUG pool-2-thread-13 internal.EntityManagerFactoryRegistry:56 - Initializing EntityManagerFactoryRegistry : [email protected] 
14:40:06,911 DEBUG pool-2-thread-13 internal.EntityManagerFactoryRegistry:66 - Registering EntityManagerFactory: something 
14:40:06,967 INFO pool-2-thread-13 jpa.LocalContainerEntityManagerFactoryBean:264 - Building JPA container EntityManagerFactory for persistence unit 'default' 
14:40:06,967 DEBUG pool-2-thread-13 type.BasicTypeRegistry:143 - Adding type registration boolean -> [email protected] 

... 

14:40:07,128 DEBUG pool-2-thread-13 internal.SessionFactoryRegistry:75 - Registering SessionFactory: 81a9b5a6-83aa-46ee-be68-d642e6fda584 (<unnamed>) 
14:40:07,128 DEBUG pool-2-thread-13 internal.SessionFactoryRegistry:82 - Not binding SessionFactory to JNDI, no JNDI name configured 
14:40:07,129 DEBUG pool-2-thread-13 internal.SessionFactoryImpl:487 - Instantiated session factory 
14:40:07,129 DEBUG pool-2-thread-13 internal.SessionFactoryImpl:1119 - Checking 0 named HQL queries 
14:40:07,129 DEBUG pool-2-thread-13 internal.SessionFactoryImpl:1142 - Checking 0 named SQL queries 
14:40:07,129 DEBUG pool-2-thread-13 internal.StatisticsInitiator:110 - Statistics initialized [enabled=false] 
14:40:07,130 DEBUG pool-2-thread-13 internal.EntityManagerFactoryRegistry:66 - Registering EntityManagerFactory: something 
14:40:07,130 WARN pool-2-thread-13 internal.EntityManagerFactoryRegistry:80 - HHH000436: Entity manager factory name (something) is already registered. If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name' 
+2

你如何初始化你的Spring應用程序上下文?你的web.xml中聲明瞭org.springframework.web.context.ContextLoaderListener嗎?你在使用Spring MVC嗎?我有時會看到Spring MVC XML配置導入其他應用程序。背景XML,造成兩次實例化一些豆子,因爲它們是在應用程序上下文和Web應用程序上下文中聲明。 – eolith

+0

是的,我是,你釘了它。 DispatcherServlet加載了與ContextLoaderListener相同的上下文文件,並加載了兩次bam,beans。新手錯誤,多麼尷尬!如果您想將您的評論改爲回答,我很樂意接受它。謝謝! –

+0

我們都是初學者,沒什麼好羞恥的。 – eolith

回答

9

你如何初始化你的Spring應用程序上下文?你在使用Spring MVC嗎?

我有時看到Spring MVC的XML配置導入其他應用程序。背景XML,造成兩次實例化一些豆子,因爲它們是在應用程序上下文和Web應用程序上下文中聲明。

12

我遇到了同樣的問題,但在不同的場景。該EntityManagerFactoryRegistry產生相同HHH000436警告,在相同的運行(即在同一個JVM)執行多個測試時,從我的IDE啓動。

問題罐表面的情況下有至少使用SpringJUnit4ClassRunner加載不同 Spring測試應用各自含有EntityManagerFactory上下文2測試類。

根本原因是Hibernate維護一個靜態的EntityManagerFactory實例註冊表,其中第二個實例的創建可能導致日誌消息的衝突。那麼爲什麼在第一次測試完成後第一個實例沒有註銷呢?它通常會在應用程序上下文包含EntityManagerFactory實例被銷燬。它測試執行過程中不會發生的原因是,Spring的測試情境框架緩存所有加載環境,以避免重新加載多個測試可能需要完全一樣的情況下。其結果是,在這些背景下豆不被摧毀,直到在最後的測試執行完畢,而Hibernate會僅僅收取有史以來所有EntityManagerFactory實例。

這的確是個問題,但如果有人是通過警告消息確實惱火,有幾個可能的方法來避免看到它:

  1. 確保EntityManagerFactory情況下獲得一個不同的名稱(它們在註冊表中按名稱鍵入)。關於名稱的派生方法,請參閱EntityManagerFactoryImpl的構造函數。
  2. 在測試類上使用@DirtiesContext可導致SpringJUnit4ClassRunner在執行測試類後立即關閉上下文並將其從上下文緩存中刪除。
  3. 只需設置的EntityManagerFactoryRegistry錯誤日誌記錄級別...

希望這可以幫助別人。

相關問題