Tags: Java 6 - JEE - Spring 2.5 - Hinernate 3.0
No persistence.xml é possível configurar, entre outras coisas, a conexão com a base de dados.
Quando o sistema é entregue ao cliente em um jar ou war, não existe uma maneira trivial de alterar as informações da base de dados, como a string de conexão, o username e o password.
Para fazer isso o cliente precisaria abrir o jar/war, alterar o persistence.xml e remontar o archive. Como nem sempre o cliente tem um time que saiba fazer isso, pode ser que você queira deixar o persistence.xml fora da pasta META-INF do seu projeto, por exemplo, em um folder de configuração do sistema em qualquer lugar do file system.
Abaixo segue o trecho a ser configurado no applicationContext.xml:
<beans ...>
<bean id="propertyPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreResourceNotFound" value="true"/>
<property name="locations">
<list>
<value>file:///${CONF_FOLDER}/dataSource.properties</value>
</list>
</property>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="file:///${persistence.path}"/>
<property name="persistenceUnitName" value="persistence-unit"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<context:annotation-config />
<context:component-scan base-package="br.com.seupackage.*"/>
</beans>
O pulo do gato aqui é a propriedade
persistenceXmlLocation do LocalContainerEntityManagerFactoryBean. Com ela você pode especificar que o persistence.xml estará em qualquer lugar do .jar ou do file system [1].
Para não deixar o caminho do persistence.xml hardcoded e como não é possível usar variável de ambiente nessa propriedade, é possível utilizar o
PropertyPlaceholderConfigurer para configurar esse path.
O arquivo dataSource.properties, que está no folder reprensentado pela variável de ambiente ${CONF_FOLDER}, tem a propriedade persistence.path com o caminho absoluto do persistence.xml.
O problema estaria resolvido aqui se não fosse um efeito colateral de mudar o persistence.xml de lugar. Quando o persistence.xml não está dentro do jar, o PU root path muda para o jar que iniciou o sistema.
Se o ponto de entrada do sistema é o jar que possuía o persistence.xml (java -jar seuSistema.jar), não tem problemas.
Caso o jar ponto de entrada do sistema chame outro jar que é o que possuía o persistence.xml, aí você terá que fazer uma modificação no persistence.xml
Um exemplo dessa arquiterura é:
projeto_gui.jar - ponto de entrada do sistema
projeto_model.jar - possui o applicationContext e o persistence
Veja a modificação no persistence.xml:
<persistence ...>
<persistence-unit name='persistence-unit'>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jar-file>file:///C:/seusistema/lib/projeto_model.jar</jar-file>
<properties>
...
<property name="hibernate.connection.provider_class"
value="org.hibernate.connection.C3P0ConnectionProvider" />
...
<property name="hibernate.connection.url" value="jdbc:oracle:thin:@192.168.0.2:1521:base" />
<property name="hibernate.connection.username" value="user" />
<property name="hibernate.connection.password" value="password" />
</properties>
</persistence-unit>
</persistence>
A tag <jar-file> foi adicionada para informar que o PU root path (o caminho que este persistence unit deve procurar as classes anotadas como Entity) é o jar que possuía o persistence.xml antes desta alteração.
Referência:
[1] LocalContainerEntityManagerFactoryBean:
http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.html#setPersistenceXmlLocation(java.lang.String)