2012-06-02 38 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错误日志记录级别...

希望这可以帮助别人。