Spring 3.1 + Hibernate 4.1 JPA,实体管理器工厂注册两次
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10866263/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring 3.1 + Hibernate 4.1 JPA, Entity manager factory is registered twice
提问by Wilson Hymanson
I'm using Spring Framework 3.1 with Hibernate 4.1 as a JPA provider, and I have a fully functional setup, but every time the web app is started I see this warning message:
我使用 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'
The application functions just fine, but warning messages like that bother me, and hours of searching and tweaking and experimenting have lead me nowhere. I've tried changing the factory name and adding and omitting chunks of configuration, all to no avail. It appears that something in Spring or Hibernate is just initializing the entity manager factory twice.
该应用程序运行良好,但像这样的警告消息困扰着我,数小时的搜索、调整和试验使我一无所获。我试过更改工厂名称并添加和省略配置块,但都无济于事。似乎 Spring 或 Hibernate 中的某些东西只是两次初始化实体管理器工厂。
FYI, I'm using the packagesToScan functionality of the LocalContainerEntityManagerFactoryBean to configure the entity manager without a persistence.xml file.
仅供参考,我正在使用 LocalContainerEntityManagerFactoryBean 的 packagesToScan 功能来配置没有 persistence.xml 文件的实体管理器。
I've pared down my spring context XML to the following and the problem persists:
我已将 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>
For completeness, here's hibernate.properties:
为了完整起见,这里是 hibernate.properties:
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.ejb.entitymanager_factory_name=something
And here's excerpted debug-level log output from both org.springframework.orm and org.hibernate. You can see how at 14:40:06,911 the EntityManagerFactory is registered from the first time, and immediately thereafter the LocalContainerEntityManagerFactoryBean appears to start all over from the beginning. Huh.
这里摘录了 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'
采纳答案by eolith
How are you initializing your Spring Application Context? Are you using Spring MVC?
你如何初始化你的 Spring 应用程序上下文?你在使用 Spring MVC 吗?
I've seen sometimes Spring MVC XML configurations importing the other app. context XML, causing instancing twice some beans because they are declared in the application context and the web application context.
我有时会看到 Spring MVC XML 配置导入其他应用程序。上下文 XML,导致某些 bean 实例化两次,因为它们是在应用程序上下文和 Web 应用程序上下文中声明的。
回答by zagyi
I came across the same issue but in a different scenario. The EntityManagerFactoryRegistryproduces the same HHH000436warning, when executing multiple tests in the same run (i.e. the same JVM) started from my IDE.
我遇到了同样的问题,但在不同的情况下。在从我的 IDE 启动的同一个运行(即同一个 JVM)中执行多个测试时,EntityManagerFactoryRegistry会产生相同的HHH000436警告。
The problem can surface in case there are at least twotest classes using the SpringJUnit4ClassRunnerto load differentSpring test application contexts each containing an EntityManagerFactory.
如果至少有两个测试类使用SpringJUnit4ClassRunner加载不同的Spring 测试应用程序上下文,每个都包含一个EntityManagerFactory.
The root cause is that Hibernate maintains a static registry of EntityManagerFactoryinstances, where the creation of the second instance may cause the collision the log message is about. So why isn't the first instance deregistered after the first test finished executing? It normally would when the app context containing that EntityManagerFactoryinstance gets destroyed. The reason it doesn't happen during test execution is that the Spring test context framework caches all loaded contexts in order to avoid re-loading the exact same context potentially needed by multiple tests. As a result, beans in these contexts doesn't get destroyed until after the last test finished executing, and Hibernate will just collect all the EntityManagerFactoryinstances ever created.
根本原因是 Hibernate 维护了一个静态的EntityManagerFactory实例注册表,其中第二个实例的创建可能会导致日志消息所涉及的冲突。那么为什么在第一个测试完成后第一个实例没有被注销?它通常会在包含该EntityManagerFactory实例的应用程序上下文被销毁时发生。在测试执行期间它不会发生的原因是 Spring 测试上下文框架缓存所有加载的上下文,以避免重新加载多个测试可能需要的完全相同的上下文。因此,在这些上下文中的 bean 直到最后一个测试完成执行后才会被销毁,并且 Hibernate 将只收集EntityManagerFactory曾经创建的所有实例。
It's really a non-issue, but if someone is really annoyed by the warning message, there are a few possible ways to avoid seeing it:
这确实不是问题,但如果有人真的对警告消息感到恼火,有几种可能的方法可以避免看到它:
- Make sure the
EntityManagerFactoryinstances get a different name (they are keyed by name in the registry). Chek the constructor ofEntityManagerFactoryImplon how the name is derived. - Use
@DirtiesContexton the test class to cause theSpringJUnit4ClassRunnerto close the context and remove it from its context cache immediately after executing the test class. - Simply set the logging level of
EntityManagerFactoryRegistryto error...
- 确保
EntityManagerFactory实例获得不同的名称(它们在注册表中按名称键入)。EntityManagerFactoryImpl检查名称如何派生的构造函数。 - 使用
@DirtiesContext的测试类导致SpringJUnit4ClassRunner关闭的背景和执行测试类后,立即从它的上下文高速缓存中删除。 - 只需将日志级别设置
EntityManagerFactoryRegistry为错误...
Hope this helps someone.
希望这可以帮助某人。

![spring 由以下原因引起的错误:org.hibernate.HibernateException:无法实例化连接提供程序 [org.connection.C3P0ConnectionProvider]](/res/img/loading.gif)