我正在使用Spring Framework 3.1和Hibernate 4.1作为JPA提供程序,我有一个功能齐全的设置,但每次启动Web应用程序时都会看到此警告消息:
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:06,911看到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 -> org.hibernate.type.BooleanType@4cb91eff
...
14:40:06,882 DEBUG pool-2-thread-13 internal.SessionFactoryRegistry:62 - Initializing SessionFactoryRegistry : org.hibernate.internal.SessionFactoryRegistry@161bb7fe
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 : org.hibernate.ejb.internal.EntityManagerFactoryRegistry@75cc9008
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 -> org.hibernate.type.BooleanType@4cb91eff
...
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'
答案 0 :(得分:12)
我遇到了同样的问题但是在不同的情况下。当从我的IDE启动同一运行(即同一JVM)中的多个测试时,EntityManagerFactoryRegistry
会产生相同的HHH000436
警告。
如果至少有两个测试类使用SpringJUnit4ClassRunner
来加载不同的 Spring测试应用程序上下文,每个包含{{1 }}
根本原因是Hibernate维护EntityManagerFactory
个实例的静态注册表,其中第二个实例的创建可能导致日志消息发生冲突。那么为什么在第一次测试完成执行后第一个实例没有注销?通常在包含该EntityManagerFactory
实例的应用程序上下文被销毁时。在测试执行期间没有发生的原因是Spring测试上下文框架缓存所有加载的上下文,以避免重新加载多个测试可能需要的完全相同的上下文。因此,在上次测试完成执行之后,这些上下文中的bean不会被销毁,而Hibernate将只收集所有创建的EntityManagerFactory
个实例。
这真的不是问题,但是如果有人对警告信息感到非常恼火,有几种方法可以避免看到它:
EntityManagerFactory
个实例获得不同的名称(它们在注册表中按名称键入)。请了解EntityManagerFactory
的构造函数,了解名称的派生方式。EntityManagerFactoryImpl
使@DirtiesContext
关闭上下文,并在执行测试类后立即将其从上下文缓存中删除。SpringJUnit4ClassRunner
的日志记录级别设置为错误... 希望这有助于某人。
答案 1 :(得分:9)
您是如何初始化Spring Application Context的?你在使用Spring MVC吗?
我有时会看到Spring MVC XML配置导入其他应用程序。上下文XML,导致两次bean的实例化,因为它们是在应用程序上下文和Web应用程序上下文中声明的。