2012-06-02 13 views
10

Estoy utilizando Spring Framework 3.1 con Hibernate 4.1 como proveedor JPA, y tengo una configuración totalmente funcional, pero cada vez que la aplicación web se inicia veo esto mensaje de advertencia:Spring 3.1 + Hibernate 4.1 JPA, la fábrica Entity Manager está registrada dos veces

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' 

La aplicación funciona muy bien, pero los mensajes de advertencia como el que me molesta, y horas de búsqueda y ajustar y experimentar tienen me llevan a ninguna parte. Intenté cambiar el nombre de la fábrica y agregar y omitir fragmentos de configuración, todo en vano. Parece que algo en Spring o Hibernate solo está inicializando la fábrica del administrador de entidades dos veces.

FYI, estoy usando la funcionalidad de packagesToScan de LocalContainerEntityManagerFactoryBean para configurar el administrador de entidades sin un archivo persistence.xml.

he recortado mi XML contexto primavera para el siguiente y el problema persiste:

<?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> 

Para completar, aquí está hibernate.properties:

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

y aquí es un extracto del registro de nivel de depuración salida de org.springframework.orm y org.hibernate. Puede ver cómo a las 14: 40: 06,911 EntityManagerFactory se registra desde la primera vez, e inmediatamente después, LocalContainerEntityManagerFactoryBean parece comenzar desde el principio. Huh.

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

¿Cómo está inicializando su contexto de aplicación Spring? ¿Tiene un org.springframework.web.context.ContextLoaderListener declarado en su web.xml? ¿Estás usando Spring MVC? A veces he visto configuraciones Spring MVC XML importando la otra aplicación. contexto XML, lo que provoca que dos veces algunos beans se declaren en el contexto de la aplicación y el contexto de la aplicación web. – eolith

+0

Sí, lo soy, y tú lo clavaste. El DispatcherServlet estaba cargando el mismo archivo de contexto que ContextLoaderListener, y bam, beans cargados dos veces. Error de principiante, ¡qué vergonzoso! Si desea reformular su comentario como respuesta, me complacería aceptarlo. ¡Gracias! –

+0

Todos somos principiantes en algo, no hay nada de qué avergonzarse. – eolith

Respuesta

9

¿Cómo está inicializando su contexto de aplicación Spring? ¿Estás usando Spring MVC?

He visto a veces configuraciones Spring MVC XML importando la otra aplicación. contexto XML, lo que provoca que dos veces algunos beans se declaren en el contexto de la aplicación y el contexto de la aplicación web.

12

Me encontré con el mismo problema pero en un escenario diferente. El EntityManagerFactoryRegistry produce la misma advertencia HHH000436 cuando se ejecutan varias pruebas en la misma ejecución (es decir, la misma JVM) desde mi IDE.

El problema puede surgir en el caso de que son al menos dos clases de prueba utilizando el SpringJUnit4ClassRunner para cargar contextos diferentes de aplicación de prueba resorte que contienen cada uno un EntityManagerFactory.

La causa raíz es que Hibernate mantiene un registro estático de las instancias EntityManagerFactory, donde la creación de la segunda instancia puede causar la colisión de la que trata el mensaje de registro. Entonces, ¿por qué no se da de baja la primera instancia después de que la primera prueba terminó de ejecutarse? Normalmente lo haría cuando el contexto de la aplicación que contiene esa instancia EntityManagerFactory se destruye. La razón por la que no ocurre durante la ejecución de la prueba es que el marco de trabajo de prueba de Spring almacena en caché todos los contextos cargados para evitar volver a cargar el mismo contexto exacto que necesitan las pruebas múltiples. Como resultado, los beans en estos contextos no se destruyen hasta que la última prueba haya terminado de ejecutarse, e Hibernate simplemente recopilará todas las instancias EntityManagerFactory que se hayan creado.

Es realmente no sea un problema, pero si alguien está realmente molesto por el mensaje de advertencia, hay algunas maneras posibles para evitar verlo:

  1. Asegúrese de que los EntityManagerFactory, se asigna un nombre diferente (que están codificados por nombre en el registro). Chek el constructor de EntityManagerFactoryImpl sobre cómo se deriva el nombre.
  2. Utilice @DirtiesContext en la clase de prueba para hacer que SpringJUnit4ClassRunner cierre el contexto y lo elimine de su caché de contexto inmediatamente después de ejecutar la clase de prueba.
  3. Basta con establecer el nivel de registro de EntityManagerFactoryRegistry a error ...

Espero que esto ayude a alguien.

Cuestiones relacionadas