web-dev-qa-db-fra.com

JPA 2.0: Ajout automatique de classes d'entités à PersistenceUnit * à partir de différents fichiers jar *

J'ai une application Java SE basée sur CDI et construite par Maven, qui comporte un module core, et d'autres modules.
Le noyau a le persistence.xml et certaines entités . Les modules ont des entités supplémentaires.

Comment puis-je ajouter les entités au projecteur de l'unité de persistance?

J'ai lu le manuel Hibernate, http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/configuration.html#setup-configuration-packaging

J'ai aussi vu ces SO questions

Je cherche une solution permettant à Hibernate d'analyser toutes les classes chargées ou de récupérer un fichier de configuration des autres fichiers JAR (comme, par exemple, CDI avec beans.xml). 

Mon application n'utilise pas Spring . Je n'insiste pas sur la portabilité - je vais rester avec Hibernate.

  • Existe-t-il une telle solution?
  • Existe-t-il un moyen de créer un PU à partir de persistence.xml et d'y ajouter des classes par programme?
  • Puis-je ajouter des classes @Entity à EntityManagerFactory après sa création?

Update: J'ai trouvé dans org.​hibernate.​ejb.​Ejb3Configuration

public Ejb3Configuration configure(String persistenceUnitName, Map integration)  

http://docs.jboss.org/hibernate/entitymanager/3.6/javadocs/

37
Ondra Žižka

Il y a plusieurs façons de le résoudre:

  1. Comme décrit dans Ai-je besoin d'éléments <class> dans persistence.xml? , vous pouvez définir la propriété hibernate.archive.autodetection et Hibernate devrait pouvoir rechercher toutes les classes annotées à partir de classpath. Cependant, ce n'est pas conforme aux spécifications JPA.

  2. Si vous utilisez Spring, à partir de Spring 3.1.2 (ou probablement un peu plus tôt), dans LocalContainerEntityManagerFactoryBean, vous pouvez définir packageToScan qui demandera à LocalContainerEntityManagerFactoryBean d'analyser dans classpath toutes les classes annotées. Encore une fois, non conforme aux spécifications JPA. 

  3. J'utilisais Maven comme outils de construction. Des années auparavant, j'ai écrit un petit plugin qui va générer persistence.xml lors du processus de construction. Le plugin va scanner depuis build classpath pour trouver toutes les classes annotées et les lister dans le fichier persistence.xml généré. Ceci est très fastidieux mais le résultat est conforme aux spécifications JPA. Un inconvénient (qui ne concerne pas la plupart des gens, je crois) est que la recherche a lieu au moment de la construction, pas à l'exécution. Cela signifie que si vous utilisez une application pour laquelle les entités JAR sont fournies uniquement au moment du déploiement/de l'exécution, mais pas au moment de la création, cette approche ne fonctionnera pas.

11
Adrian Shum

Ejb3Configuration a été supprimé de la version 4.3.0. Si vous ne souhaitez pas créer d'intégrateur Hibernate, vous pouvez utiliser la propriété hibernate.ejb.loaded.classes.

properties.put(org.hibernate.jpa.AvailableSettings.LOADED_CLASSES, entities);
Persistence.createEntityManagerFactory("persistence-unit", properties);

entities est un List<Class> de classes d'entités.

7
Ignacio Baca

J'ai une configuration légèrement différente dans laquelle je place persistence.xml dans le fichier WAR, mais certaines de ses dépendances incluent @Entity annoté, classé pour l'inclure dans l'unité de persistance. 

J'ai résolu mon problème en utilisant Maven un peu comme Adrian Shum décrit dans le n ° 3, mais en utilisant l'élément pour inclure les bocaux à analyser pour les annotations @Entity. 

J'ai ajouté une propriété à my-web/pom.xml pour chaque dépendance, y compris des entités supplémentaires. Tous mes pots font partie d'un multiprojet Maven, donc pour moi ça ressemble. 

<properties>
    <common.jar>common-${project.version}.jar</common.jar>
    <foo.jar>foo-${project.version}.jar</foo.jar>
</properties>

J'ajoute ensuite ce qui suit au fichier persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" ... >
    <persistence-unit name="primary">
        <jta-data-source>Java:jboss/datasources/mysource</jta-data-source>

        <jar-file>lib/${common.jar}</jar-file>
        <jar-file>lib/${foo.jar}</jar-file>

        ...
    </persistence-unit>
</persistence>

Enfin, je configure le plugin maven-resource-web de pom.xml pour remplacer les expressions $ de persistence.xml par les propriétés définies dans le POM.

<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
      <includes>
        <include>**/persistence.xml</include>
      </includes>
    </resource>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>false</filtering>
      <excludes>
        <exclude>**/persistence.xml</exclude>
      </excludes>
    </resource>
  </resources>
  ...
</build>
5
Jesper Tejlgaard

J'ai rencontré le même problème et malheureusement, il n'y a pas de solution facile, il semblerait que JPA n'ait pas été conçu pour être utilisé de cette façon. Une des solutions consiste à n'avoir que un persistence.xml par projet (application) de niveau supérieur. C'est un peu similaire à la configuration de log4j. Le fichier persistence.xml doit répertorier toutes les classes (à l'aide de <class>) ou, si ce n'est pas l'application Java SE, les fichiers jar (à l'aide de <jar-file>) utilisés par l'application. De cette façon, vous pouvez placer des entités de plusieurs modules (jars) dans une seule unité de persistance. L'inconvénient est évident: vous devez tout répertorier dans un seul fichier.

EDIT: J'ai (éventuellement) trouvé une autre solution qui utilise des fichiers de mappage XML, consultez-la ici: Plusieurs jars, solution à unité de persistance unique?

3
Adam Dyga

Vous pouvez utiliser ce concept: https://wiki.Eclipse.org/Packaging_and_Deploying_EclipseLink_JPA_Applications_(ELUG)

<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
   <persistence-unit name="mamcaPU" transaction-type="JTA">
        <provider>org.Eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>mamcaPU</jta-data-source>
        <mapping-file>/META-INF/common-layer-mappings.xml</mapping-file>
    </persistence-unit>
</persistence>

common-layer-mappings.xml

<entity-mappings>   
   <entity class="vub.be.mamca.entity.Surveyactorgrouptable"></entity>
   <entity class="vub.be.mamca.entity.Userevaluationelicitationtable"></entity>
   <entity class="vub.be.mamca.entity.Userevaluationtable"></entity>
   <entity class="vub.be.mamca.entity.Usertable"></entity>
   <entity class="vub.be.mamca.entity.Userweightelicitationtable"></entity>
</entity-mappings>
1
Tunde Pizzle

J'ai un problème similaire et résolu avec Hibernate/ Integrator SPI:

@Override
public void integrate(Configuration configuration,
    SessionFactoryImplementor sessionFactory,
    SessionFactoryServiceRegistry serviceRegistry) {

    configuration.addAnnotatedClass(MyEntity.class);
    configuration.buildMappings();
}

L'intégrateur est fourni en tant que service Java .

0
Markus Malkusch

Double possible, voir ma question SO

Nous avons rencontré le même problème et le seul moyen que nous avons trouvé consistait à accumuler toutes les entités dans un seul fichier persistence.xml pour l'application (Web) finale. 

Dans le même temps, nous définissons des fichiers persistence.xml distincts dans nos ressources de test afin de pouvoir exécuter des tests d'acceptation par module.

0
Pete