2012-03-28 11 views
6

OK, scusate, ho cercato risposte a questo per ore, ma mi ci è voluto inserire tutta la domanda per StackOverflow per chiarire il link che stavo cercando. È possibile leggere molte informazioni rilevanti here.Utilizzo di file persistence.xml separati per la produzione e il test con Spring 3.1


Ho un progetto primavera creata con Spring Roo da usare Hibernate e MySQL. Tuttavia, per i test, voglio usare HSQLDB in memoria perché i test di integrazione Roo cancellano i dati con ID (chiavi primarie) da 0 a 10 (piuttosto che cancellare i dati usando gli ID assegnati dal database per i dati che hanno già creato), il che significa che cancella i dati già presenti nel database, che nel mio caso causano una violazione del vincolo prima che possa aggirare il rollback della transazione.

Questo è un po 'più difficile perché sto cambiando interi provider di database che significa diversi dialetti Hibernate così come diverse impostazioni DDL (convalidare in produzione, creare-rilasciare in prova). Ma non funziona come mi aspetto e sono perplesso sul perché.

Se sai perché non funziona, ti preghiamo di dirlo, anche se non hai una soluzione.

Essendo un progetto Roo, sto utilizzando Maven, ovviamente. Quindi, la prima cosa che ho provato è stata la creazione di un file specifico per il test src/test/resources/META-INF/persistence.xml e un file specifico per il test src/test/resources/META-INF/spring/database.properties. Che non ha funzionato, come quando mi sono imbattuto mvn test tutto rotto, con il relativo messaggio essendo

Conflicting persistence unit definitions for name 'persistenceUnit' 

Perché mvn test ancora raccogliendo la risorse non prova?

Quindi ho rinominato src/test/resources/META-INF/spring in spring-test e ho copiato applicationContext.xml in esso. Ho cambiato la configurazione del contesto nelle classi di test per

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

Completamento (o così ho pensato) separazione, ho fatto un paio di modifiche da spring-test/applicationContext.xml:

Modificato il percorso dei file proprietà:

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

a

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

Modificato il nome dell'unità di persistenza:

<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 ho fatto la corrispondente variazione nella persistenza nome dell'unità a src/test/resources/META-INF/persistence.xml

Beh, OK, ora non c'è alcun conflitto, ma in qualche modo Hibernate ha perso le mappature delle entità (es per l'entità Product) e ottengo:

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

Perché ha Primavera/Hibernate perso le mappature di entità in questa configurazione?

Quindi la prossima cosa che ho provato è stata la fusione dei due file persistence.xml in modo che un file sotto src/main/resources/META-INF includa entrambe le unità di persistenza.

Che funziona !! ??

Penso che sia brutto, perché ora ho la configurazione di test nel mio codice di produzione, ma è quello che sto ottenendo con.

Che cos'è un modo migliore?

Sono a conoscenza del fatto che le proprietà non sono disponibili all'interno di persistence.xml nel modo in cui si trovano all'interno dei file XML di Spring. Quindi non penso di poter fare ciò che voglio con solo un file di proprietà specifico del test.

Idealmente eseguirò i test utilizzando tutta la configurazione in src/main/resources eccetto ciò che è sovrascritto in src/test/resources. C'è un modo per realizzare questo?

Grazie per qualsiasi suggerimento è possibile fornire!

risposta

1

Nel mio lavoro, ho usato configurare persistence.xml senza le informazioni della connessione al database. La connessione al database è definita dalla configurazione del contesto di Spring. Nel quadro di Primavera, ci sono diversi modo per modificare le proprietà di un oggetto:

  1. PropertyPlaceholderConfigurer - Utilizzando file di proprietà diversa per ignorare il valore della connessione al database o dialetto ORM. È possibile utilizzare resource filter per generare valori diversi di un singolo file di proprietà se si utilizza Maven
  2. Bean definition inheritance - Utilizzare un'altra configurazione di contesto per "sovrascrivere" la configurazione predefinita.

A seguito di codice è un estratto dal mio contesto di applicazione:

<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" 
/> 
<!-- :~) --> 

Ecco la configurazione per il test:

<!-- 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" 
/> 

Quando sto facendo funzionare prova, ho impostare le proprietà del sistema in Maven surefire per configurare database diversi. Come esempio seguente:

<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

Grazie, Mike. Conservo le informazioni del database anche in un file delle proprietà. Quello che non ho visto è stato come modificare il dialetto SQL di Hibernate tramite le proprietà, mentre configuro Hibernate nel persistence.xml. –

Problemi correlati