2012-03-28 15 views
6

OK, lo siento, buscaba respuestas a esta durante horas, pero me tomó de entrar en toda la cuestión de Stackoverflow a propagarse por el enlace que estaba buscando. Puede leer mucha información relevante here.Uso de archivos persistence.xml separados para la producción y prueba con Spring 3.1


Tengo un proyecto de primavera creado con Spring Roo para utilizar Hibernate y MySQL. Sin embargo, para probar, quiero usar HSQLDB en memoria porque las pruebas de integración de Roo eliminan datos con ID (claves principales) del 0 al 10 (en lugar de eliminar los datos usando identificadores asignados a la base de datos para los que ya han creado), lo que significa borra datos que ya están en la base de datos, lo que en mi caso causa una violación de restricciones antes de que se revierta la transacción.

Esto es un poco más difícil porque estoy cambiando proveedores enteros de bases de datos lo que significa diferentes dialectos Hibernate así como diferentes configuraciones DDL (validar en producción, crear-soltar en prueba). Pero no está funcionando como esperaba y estoy perplejo sobre por qué.

Si usted sabe por qué no está funcionando, por favor decirlo, incluso si usted no tiene una solución.

Esta siendo un proyecto Roo, estoy usando Maven, por supuesto. Entonces, lo primero que intenté fue tener un archivo src/test/resources/META-INF/persistence.xml específico de la prueba y, asimismo, un archivo src/test/resources/META-INF/spring/database.properties específico de la prueba. Eso no funcionó, como cuando me encontré mvn test todo lo rompió, con el mensaje relevante siendo

Conflicting persistence unit definitions for name 'persistenceUnit' 

¿Por qué se mvn test tratando de recuperar los recursos no pruebas?

Entonces cambié el nombre a src/test/resources/META-INF/spring en spring-test y copié applicationContext.xml en él. He cambiado la configuración de contexto en las clases de prueba a

@ContextConfiguration(locations = "classpath:/META-INF/spring-test/applicationContext*.xml")

Finalización (o eso creía yo) la separación, me hizo un par de ediciones a spring-test/applicationContext.xml:

cambia la ruta para los archivos de propiedades:

<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/> 

a

<context:property-placeholder location="classpath*:META-INF/spring-test/*.properties"/> 

cambió el nombre de la unidad de persistencia:

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> 
    <property name="persistenceUnitName" value="persistenceUnit"/> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 

a

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> 
    <property name="persistenceUnitName" value="testPersistenceUnit"/> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 

E hice el cambio correspondiente en la persistencia nombre de la unidad de src/test/resources/META-INF/persistence.xml

Pues bien, ahora no hay conflicto, pero de alguna manera Hibernate ha perdido las asignaciones de entidades (por ejemplo, para la entidad Product) y me sale:

org.springframework.dao.InvalidDataAccessApiUsageException: 
org.hibernate.hql.ast.QuerySyntaxException: Product is not mapped [SELECT o FROM Product o]; 

Por qué ha perdido Primavera/Hibernate las asignaciones de entidad en esta configuración?

Así que lo siguiente que intenté fue fusionar los dos archivos persistence.xml de modo que un archivo en src/main/resources/META-INF incluye ambas unidades de persistencia.

que funciona !! ??

Creo que es feo, porque ahora tengo la configuración de prueba en mi código de producción, pero es lo que estoy logrando.

¿Qué es una mejor manera?

es mi entendimiento de que las propiedades no están disponibles dentro de persistence.xml la forma en que se encuentran dentro de los archivos XML de primavera. Así que no creo que pueda hacer lo que quiero con solo un archivo de propiedades específico de prueba.

Lo ideal sería ejecutar pruebas utilizando toda la configuración, en src/main/resources excepto por lo que se anula específicamente en src/test/recursos. ¿Hay alguna manera de lograr esto?

Gracias por cualquier idea que se puede brindar!

Respuesta

1

En mi trabajo, solía configurar persistence.xml sin la información de conexión a la base de datos. La conexión de la base de datos está definida por la configuración de contexto de Spring. En el marco de primavera, hay varias manera de cambiar las propiedades de un objeto:

  1. PropertyPlaceholderConfigurer - Uso de diferentes archivo de propiedades para anular el valor de conexión de base de datos o dialecto del ORM. Puede usar resource filter para generar valores diferentes de un solo archivo de propiedad si está usando Maven
  2. Bean definition inheritance - Usando otra configuración de contexto para "anular" la configuración predeterminada.

siguiente código es un extracto de mi contexto de aplicación:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" 
    p:location="classpath:frontend.properties" p:ignore-resource-not-found="true" 
    p:systemPropertiesModeName="SYSTEM_PROPERTIES_MODE_OVERRIDE" 
/> 

<util:properties id="jpaProperties"> 
    <prop key="hibernate.dialect">${hibernate.dialect}</prop> 
</util:properties> 

<!-- Global entity manager factory(may not be overrided) --> 
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
    p:dataSource-ref="dataSource" p:jpaProperties-ref="jpaProperties" 
> 
    <property name="JpaDialect"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> 
    </property> 
</bean> 
<!-- :~) --> 

<!-- Data Source --> 
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close" 
    p:driverClass="${database.driverClass}" p:jdbcUrl="${database.url}" 
    p:username="${database.username}" p:password="${database.password}" 
    p:partitionCount="${database_conn.pooling.partition_count:2}" 
    p:maxConnectionsPerPartition="64" p:minConnectionsPerPartition="${database_conn.pooling.min_connections:4}" 
    p:acquireIncrement="4" p:statementsCacheSize="64" 
    p:connectionTimeoutInMs="1800000" p:IdleConnectionTestPeriodInMinutes="420" 
/> 
<!-- :~) --> 

Aquí es la configuración para la prueba:

<!-- import configuration of application --> 
<import resource="classpath:database.xml" /> 

<!-- 
    - I override some of settings of connection pooling while testing 
    --> 
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close" 
    p:driverClass="${database.driverClass}" p:jdbcUrl="${database.url}" 
    p:username="${database.username}" p:password="${database.password}" 
    p:maxConnectionsPerPartition="8" p:minConnectionsPerPartition="2" 
    p:acquireIncrement="2" p:statementsCacheSize="32" 
/> 

Cuando estoy corriendo prueba, configurar las propiedades del sistema en Maven surefire para configurar diferentes bases de datos. Como muestra siguiente:

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-surefire-plugin</artifactId> 
    <version>2.8.1</version> 
    <configuration> 
     <systemPropertyVariables> 
      <!-- Using HSQLDB as test database system --> 
      <database.driverClass>org.hsqldb.jdbc.JDBCDriver</database.driverClass> 
      <database.url>${database.hsqldb.url}</database.url> 
      <database.username>any</database.username> 
      <database.password>any</database.password 
      <hibernate.dialect>org.hibernate.dialect.HSQLDialect</hibernate.dialect> 
      <!-- :~) --> 
     </systemPropertyVariables> 
    </configuration> 
</plugin> 
+0

Gracias, Mike. También guardo la información de la base de datos en un archivo de propiedades. Lo que no vi fue cómo cambiar el dialecto SQL de Hibernate a través de propiedades, ya que configuro Hibernate en persistence.xml. –

Cuestiones relacionadas