2011-09-16 7 views
21

Estamos desarrollando una aplicación web con Spring, Hibernate y Maven de una forma muy modular. Hay proyectos centrales que definen el acceso a los datos y ver cosas específicas, luego hay módulos que definen la lógica y las entidades (@Entity) y luego está la aplicación web que define el controlador y la vista.JPA - múltiples jarros que definen objetos de @Entity

Ahora tenemos un módulo de seguridad que define entidades de seguridad como la cuenta y el rol, y tenemos un módulo prototipo que define algunas entidades de ejemplo, como cliente y pedido. Ambos tienen un PersistenceUnit definido dentro de un persistence.xml que está prácticamente vacío excepto por el nombre de PersistenceUnit, ya que toda la configuración de la base de datos se realiza en la aplicación web con un datasource.xml. Se supone que la aplicación web carga ambas jarras como dependencias maven.

Ambos proyectos construirán bien, autocifrarán todas las entidades y las crearán para sus respectivas pruebas unitarias. También se cargarán correctamente dentro de la aplicación web si se agregan individualmente.

Sin embargo, tan pronto como ambos se carguen al mismo tiempo, el segundo anulará el PersistenceUnit del primero y creará así un IllegalArgumentException : Not an entity para todas las entidades del primero. Si ambos proyectos tienen una unidad de persistencia diferente, la carga de la aplicación web arrojará otra excepción diciendo que no single default persistence unit se definió.

Así que .. ¿cómo puedo obtener todas las clases @Entity anotados para cargar en mi aplicación web sin tener que definir todos ellos dentro de la persistence.xml (como here), sino más bien a través de los componentes de análisis? This parece una idea, aunque no sé cómo usarla y probarla ...

Creo que debemos fusionar todas las unidades de persistencia dentro de la aplicación web o cargar todas las entidades mediante programación. Definirlos con código fijo dentro de persistence.xml no es una opción para nosotros.

+0

en relación con la primera respuesta: Por lo que yo sé , Spring ya escanea para las clases anotadas y las agrega a la 'PersistenceUnit'. El problema es que tengo que nombrar todas las 'PersistenceUnits' de la misma manera, lo que hará que se anulen entre sí. Así que estoy buscando una manera de combinar todas las PersistenceUnits en una en mi aplicación web. No sé si [esto] [1] (abajo) haría, aunque no tengo idea de dónde registrar un 'MergingPersistenceUnitPostProcessor' [1]: http://forum.springsource.org/showthread.php? 61763-Problems-with-JPA-and-multiple-persistence-units – Pete

Respuesta

4

Usamos un diseño de módulo similar, pero colocamos el contexto de persistencia en la parte war de nuestra aplicación e inyectamos el entitymanager en los DAO de los módulos. Excepto para las pruebas unitarias, los módulos no tienen una PU. Lo hicimos porque teníamos miedo, , de que una transacción que abarca varios módulos podría causar problemas.

En el DAO

@PersistenceContext 
private EntityManager em; 

En el persistance.xml que necesita para dar de alta a todas las entidades con los elementos.

<persistence-unit name="myPU"> 
    <class>com.Entity1</class>  
<class>com.Entity2</class> 

etc.

+1

Ya veo ... Intenté ese enfoque y funciona . Pero, ¿no es bastante complicado tener que actualizar ese archivo persistence.xml (más los archivos unit persistence.xml)? ¿No hay una forma dinámica de cargarlo todo automáticamente? – Pete

+2

Teóricamente hay una función de escaneo automático en tiempo de ejecución (¿depende del proveedor de JPA? No estoy seguro) pero descubrí que no siempre funciona. En mi compañía, escribí un plugin de Maven, que se ejecuta en el proyecto de guerra al compilar, para generar automáticamente la base persistence.xml en todas las clases anotadas @Entity en classpath. –

+0

Buena idea, eso es al menos algo automatizado y podría proporcionar el último persistence.xml antes de la ejecución de la prueba unitaria. ¿Puedes publicar algún puntero a los elementos clave de tu complemento? No he hecho esto antes ... (Ya puedo pensar en un segundo caso de uso para esto, crear tipos de consulta para queryDSL, ya que el último complemento parece estar roto) – Pete

3

Las clases estarán en el cargador de clases.

Responda Scanning Java annotations at runtime.

¿Eso es lo que quieres? Para buscar @Entity anotado y agréguelos a PersistenceUnit?

Atentamente.

+0

+1, ya que necesitaré esto pronto para escanear @PreAuthorize Annotations – Pete

+0

@Pete ¡gracias! Ç – ssedano

3

Bueno, estamos teniendo un problema similar en nuestro ciclo de desarrollo. Si sus entidades de referencia están en otro -ejb.archivo jar (que es nuestro caso) se puede enlazar estas entidades con

<jar-file>relativePathToYourJar/dependent-entities-ejb.jar</jar-file>

etiqueta. Tenga en cuenta que también debe incluir un persistence.xml en dependent-entities-ejb.jarMETA-INF carpeta. Se puede encontrar más información en here.

4

Dado que la pregunta parece llamar la atención, publicaré nuestra última solución al problema.

Ahora somos escaneo automático de todos los paquetes en lugar de utilizar persistence.xml archivos en cualquier lugar.

En nuestra datasource.xml añadimos la línea

<property name="packagesToScan" value="our.basepackage" /> 

datasource.xml casi completa:

<!-- Bean definition here --> 

<bean id="ourDataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
      <!-- define connection properties -->  
</bean> 


<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="ourDataSource" /> 
    <property name="packagesToScan" value="our.basepackage" /> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="showSql" value="false" /> 
      <property name="generateDdl" value="true" /> 
      <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" /> 
     </bean> 
    </property> 

</bean> 

<tx:annotation-driven transaction-manager="transactionManager" /> 
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" /> 

+0

Pero esto no ayudará si no inicia su aplicación. No podrá generar metamodelo estático usando esta configuración. – kboom

Cuestiones relacionadas