JPA utilizando la alternativa “persistence.xml”

Sé que con la instrucción:

Persistence.createEntityManagerFactory("persistence-unit-name"); 

El mecanismo de persistencia JPA lee el archivo “persistence.xml”, busca la unidad de persistencia llamada “nombre-unidad de persistencia” y construye el EntityManagerFactory en función de él.

Mi pregunta es, ¿cómo puedo forzar a JPA a tomar un archivo diferente de “persistence.xml” ? por ejemplo, “persistence-test.xml”.

No hay una forma JPA estandarizada para hacer esto, aunque los proveedores de JPA individuales pueden proporcionar una forma. Sugeriría la forma estándar de tener una ruta de clase diferente para main y test.

Por ejemplo, si usa Maven y tiene dos archivos META-INF/persistence.xml , uno en src/main/resources y otro en src/test/resources , las pruebas recogerán el de src/test/resources , porque Maven coloca las clases / recursos de prueba por delante de las clases / recursos principales en el classpath. Puede configurar fácilmente Ant para que funcione de forma similar.

Si necesita una lógica más avanzada, considere usar el soporte JPA de Spring . Le permitirá tratar situaciones avanzadas como la integración de múltiples archivos persistence.xml .

En EclipseLink puedes hacer lo siguiente:

 Properties pros = new Properties(); pros.setProperty(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML, "META-INF/persistence-alternative.xml"); EntityManagerFactory factory = Persistence.createEntityManagerFactory("pu-name", pros); 

No creo que puedas. El largo camino para hacer esto es:

  • Cree una Fábrica que lea su persistence-test.xml y represente las persistence-test.xml un Map y.
  • Llame a Persistence.createEntityManagerFactory(persistenceUnitName, Map properties) . De esta forma, se lee desde el mapa de properties en lugar de leer desde persistence.xml .

Si usaba OpenEJB para conducir sus pruebas, podría hacer exactamente lo que quiera utilizando el proveedor de JPA que desee. Pregunta similar y la respuesta relacionada aquí:

¿Cómo hacer que Maven ignore mi main / resources / persistence.xml a favor de test / …?

Puede configurar Hibernate sin usar persistence.xml en Spring como esto:

 @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() { Map properties = new Hashtable<>(); properties.put("javax.persistence.schema-generation.database.action", "none"); HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter(); adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect"); //you can change this if you have a different DB LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(adapter); factory.setDataSource(this.springJpaDataSource()); factory.setPackagesToScan("package name"); factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE); factory.setValidationMode(ValidationMode.NONE); factory.setJpaPropertyMap(properties); return factory; } 

Como no está utilizando persistence.xml, debe crear un bean que devuelva DataSource que especifique en el método anterior que establece el origen de datos:

 @Bean public DataSource springJpaDataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setUrl("jdbc:mysql://localhost/SpringJpa"); dataSource.setUsername("tomcatUser"); dataSource.setPassword("password1234"); return dataSource; } 

Luego usa la anotación @EnableTransactionManagement sobre este archivo de configuración. Ahora, cuando pones esa anotación, debes crear un último bean:

 @Bean public PlatformTransactionManager jpaTransactionManager() { return new JpaTransactionManager( this.entityManagerFactoryBean().getObject()); } 

Ahora, no se olvide de usar @Transactional Annotation sobre aquellos métodos que tratan con DB.

Por último, no olvide inyectar EntityManager en su repository (esta clase de repository debe tener @Repository anotación de @Repository ).

Entonces queremos tener 2 archivos separados persistence.xml . Uno debe leerse únicamente por configuración de producción y el otro para pruebas. La idea es cambiar el nombre u ocultar los archivos de producción .

Solución de guerra

No coloque persistence.xml en src\main\resources\META-INF\ . En su lugar, póngalo en src\main\webapp\WEB-INF\classes\META-INF\ . Esa es la ubicación donde debería estar el archivo y en este lugar no será visible mediante pruebas.

Esta solución funciona para mí en el entorno gradle, pero espero que otros también lo hagan.

Solución Jar

Cambie el nombre del archivo de producción a persistence-ee.xml . Ahora hemos terminado con la configuración de prueba. Para la producción debemos emplear algún procesamiento. Cada entorno puede tener su propio camino, así es como lo hago en gradle:

 tasks.withType(Jar) { rename { fileName -> fileName == "persistence-ee.xml" ? "persistence.xml" : fileName; } } 

En mis aplicaciones, el archivo persistence.xml para producción solo es necesario en el momento del despliegue, es decir, en los paquetes jar / war. Y estos son los únicos lugares donde este archivo es visible. Sin doble persistence no pude iniciar mi base de datos. La razón principal fue el uso de jta-data-source , la otra: 2 unidades de persistencia con nombre separadas.