web-dev-qa-db-fra.com

Partage d'une unité de persistance entre les composants dans un fichier .ear

Dans une application Java EE 6 où j'utilise un package .ear, je voudrais créer une unité de persistance accessible à partir de composants dans différents fichiers .jar.

Cependant, je ne sais pas comment définir cette unité de persistance. Avec l'annotation @PersistenceContext, la recherche réussit uniquement si le nom correspond à une unité de persistance définie dans le fichier local persistence.xml.

Est-il possible de se référer à des unités de persistance externes?

34
bamoida2010

Voici les sections pertinentes de la spécification JPA 2.0:

8.2 Emballage de l'unité de persistance

...

Une unité de persistance est définie par un fichier persistence.xml. Le fichier jar ou le répertoire dont le répertoire META-INF Contient le fichier persistence.xml Est appelé la racine de l'unité de persistance. Dans les environnements Java EE, la racine d'une unité de persistance doit être l'une des suivantes:

  • un fichier EJB-JAR
  • le répertoire WEB-INF/classes d'un fichier WAR [80]
  • un fichier jar dans le répertoire WEB-INF/lib d'un fichier WAR
  • un fichier jar dans le répertoire de la bibliothèque EAR
  • un fichier jar de client d'application

Il n'est pas nécessaire qu'un fichier EJB-JAR ou WAR contenant une unité de persistance soit conditionné dans un EAR, sauf si l'unité de persistance contient des classes de persistance en plus de celles contenues dans EJB-JAR ou WAR. Voir section 8.2.1.6.

REMARQUE: Java Persistence 1.0 a pris en charge l'utilisation d'un fichier jar à la racine de l'EAR comme racine d'une unité de persistance. Cette utilisation n'est plus prise en charge. Les applications portables devraient utiliser à la place le répertoire de la bibliothèque EAR . Voir [9].

Une unité de persistance doit avoir un nom. Une seule unité de persistance d'un nom donné doit être définie dans un seul fichier EJB-JAR, dans un seul fichier WAR, dans un seul fichier client d'application ou dans un fichier EAR. Voir Section 8.2.2, "Portée de l'unité de persistance".

Le fichier persistence.xml Peut être utilisé pour désigner plusieurs unités de persistance dans la même étendue.

Toutes les classes de persistance définies au niveau du Java EE EAR doivent être accessibles à tous les autres Java EE composants dans le application - c'est-à-dire chargée par le chargeur de classe d'application - de telle sorte que si la même classe d'entité est référencée par deux composants EE Java EE (qui peuvent utiliser différentes unités de persistance) ), la classe référencée est la même classe identique.

Et ensuite:

8.2.2 Portée de l'unité de persistance

Un EJB-JAR, un fichier WAR, un fichier client d'application ou un fichier EAR peut définir une unité de persistance.

Lors du référencement d'une unité de persistance à l'aide de l'élément d'annotation unitName ou de l'élément de descripteur de déploiement persistence-unit-name, La portée de visibilité de l'unité de persistance est déterminée par son point de définition:

  • Une unité de persistance définie au niveau d'un fichier EJB-JAR, WAR ou client d'application est portée respectivement à ce fichier EJB-JAR, WAR ou application et est visible par les composants définis dans ce fichier ou guerre.
  • Une unité de persistance définie au niveau de l'EAR est généralement visible par tous les composants de l'application . Cependant, si une unité de persistance du même nom est définie par un EJB-JAR, WAR ou un fichier jar d'application dans l'EAR, l'unité de persistance de ce nom définie au niveau EAR ne sera pas visible pour les composants définis par ce fichier JAR EJB-JAR, WAR ou d'application, sauf si la référence d'unité de persistance utilise la syntaxe du nom d'unité de persistance # pour spécifier un nom de chemin pour lever l'ambiguïté de la référence. Lorsque la syntaxe # Est utilisée, le nom du chemin est relatif au fichier jar du composant d'application référençant. Par exemple, la syntaxe ../lib/persistenceUnitRoot.jar#myPersistenceUnit Fait référence à une unité de persistance dont le nom, comme spécifié dans l'élément name du fichier persistence.xml, Est myPersistenceUnit et pour lequel le nom de chemin relatif de la racine de l'unité de persistance est ../lib/persistenceUnitRoot.jar. La syntaxe # Peut être utilisée avec l'élément d'annotation unitName ou l'élément descripteur de déploiement persistence-unit-name Pour référencer une unité de persistance définie au niveau EAR.

Vous devez également inclure le jar des classes d'entité dans le manifeste du jar pu http://wiki.Eclipse.org/Packaging_and_Deploying_EclipseLink_JPA_Applications_ (ELUG)

Pour résumer, vous devriez être en mesure de définir vos entités et l'unité de persistance au niveau supérieur de l'EAR et de les utiliser à partir des autres modules.

Je ne suis tout simplement pas sûr de comprendre ce que vous avez essayé et les problèmes auxquels vous avez été confronté.

47
Pascal Thivent

Le problème peut être résolu en plaçant un fichier persistence.xml dans un fichier jar situé dans le répertoire lib de l'oreille.

Le fichier persistence.xml doit contenir les fichiers jar qui incluent les entités. J'ai dû donner le chemin relatif aux fichiers jar. Structure du répertoire de mon oreille

|-ear--
       |-lib--|... some libs ...
       |      |--my-persistence-xml.jar
       |-ejb-with-entities1.jar
       |-ejb-with-entities2.jar

Mon persistence.xml pour jboss 7.1.1

<persistence-unit name="my-pu" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>Java:jboss/datasources/mypu</jta-data-source>
    <jar-file>../ejb-with-entities1.jar</jar-file>
    <jar-file>../ejb-with-entities1.jar</jar-file>
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
        <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.format_sql" value="true" />
    </properties>
 </persistence-unit>

J'espère que cela t'aides

14
christian

Tout ce dont tu as besoin

EAR +
    |- META-INF +
    |       - persistence.xml
    |- ejb1-module.jar
    |- ejb2-module.jar


<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://Java.Sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="my-persistence-unit">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>MyDataSource</jta-data-source>
        <!-- Note: it's relative to `persistence-module.jar` file location in EAR -->
        <jar-file>../ejb1-module.jar</jar-file>
        <jar-file>../ejb2-module.jar</jar-file>
        <properties>
            ...

        </properties>
    </persistence-unit>
</persistence>
9
jprism

Exemple de disposition EAR de travail pour Glassfish:

EAR +
    |- lib +
    |      |- core-module.jar
    |      \- persistence-module.jar +
    |                                 \- META-INF +
    |                                              \- persistence.xml
    |- ejb1-module.jar
    \- ejb2-module.jar

Les modules EJB peuvent être des archives jar ou des répertoires éclatés.

Dans ce cas, votre persistence.xml peut ressembler à:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://Java.Sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="my-persistence-unit">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>MyDataSource</jta-data-source>
        <!-- Note: it's relative to `persistence-module.jar` file location in EAR -->
        <jar-file>../ejb1-module.jar</jar-file>
        <jar-file>../ejb2-module.jar</jar-file>
        <properties>
            <property name="hibernate.current_session_context_class" value="jta"/>
            <property name="hibernate.id.new_generator_mappings" value="true"/>
            <property name="hibernate.dialect"      value="org.hibernate.dialect.PostgreSQL82Dialect"/>
            <property name="hibernate.show_sql"     value="true"/>
            <property name="hibernate.format_sql"   value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>

Vous devez mettre à jour <jar-file> références si vous utilisez la gestion des versions de module (par exemple ejb1-module-1.0-SNAPSHOT.jar).

Objets abstraits avec @MappedSuperclass annotation et EntityManager injection peuvent être placés dans n'importe quel pot externe. Ce pot n'a pas besoin d'être mentionné dans persistence.xml. Par exemple, vous pouvez créer core-module.jar avec PersistableEntity.Java:

public class PersistableEntity {
    @Id
    @GeneratedValue
    private Long id;

    public Long getId() { return id; }

    public Integer getVersion() { return version; }
}

Et PersistableEntityManager.Java:

public class PersistableEntityManager<T extends PersistableEntity> {
    @PersistenceContext
    protected EntityManager em;
}

Ce core-module.jar pourrait être utilisé par tous vos projets avec différentes unités de persistance. Vous héritez simplement de vos Entités et EJB et évitez le passe-partout. Consultez l'exemple bilionix-core sur github .

6

Essayez avec ceci:

  1. Configurez le fichier EAR application.xml de cette manière:

    http://xmlns.jcp.org/xml/ns/javaee/application_7.xsd "version =" 7 "> YourEEApplication

    <initialize-in-order>true</initialize-in-order> <!-- This is the most important thing -->
    
    <module>
        <ejb>YourEJBModule1.jar</ejb>
    </module>
    <module>
        <ejb>YourEJBModule2.jar</ejb>
    </module>
    ......
    <module>
        <ejb>YourEJBModuleX.jar</ejb>
    </module>
    
    <module>
        <web>
            <web-uri>YourWebModule.war</web-uri>
            <context-root>YourWebModule</context-root>
        </web>
    </module>
    
  2. Dans vos projets EJB YourEJBModule1, YourEJBModule2 ... et YourEJBModuleX:

Injecter le contexte de persistance sans la propriété unitName:

@PersistenceContext(type=PersistenceContextType.TRANSACTION)
    private EntityManager em; // get & set
  1. Pour chaque fichier persistence.xml du module EJB:

YourEJBModule1:

<?xml version="1.0" encoding="UTF-8"?>
<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="PersistenceUnit1"
        transaction-type="JTA">
        <provider>org.Eclipse.persistence.jpa.PersistenceProvider</provider>

        <jta-data-source>jdbc/YourDataSource</jta-data-source>
        <class>com.example.Foo1</class>
        <!-- Other properties -->
    </persistence-unit>
</persistence>

YourEJBModule2:

<?xml version="1.0" encoding="UTF-8"?>
...
    <persistence-unit name="PersistenceUnit2"
        transaction-type="JTA">
        <provider>org.Eclipse.persistence.jpa.PersistenceProvider</provider>

        <jta-data-source>jdbc/YourDataSource</jta-data-source>
        <jar-file>YourEJBModule1.jar</jar-file>
        <class>com.example.Foo2</class>
        <!-- Other properties -->
    </persistence-unit>
...

YourEJBModuleX:

<?xml version="1.0" encoding="UTF-8"?>
...
    <persistence-unit name="PersistenceUnitX"
        transaction-type="JTA">
        <provider>org.Eclipse.persistence.jpa.PersistenceProvider</provider>

        <jta-data-source>jdbc/YourDataSource</jta-data-source>
        <jar-file>YourEJBModule1.jar</jar-file>
        <jar-file>YourEJBModule2.jar</jar-file>
        ......
        <class>com.example.FooX</class>
        <!-- Other properties -->
    </persistence-unit>
...

Dans la base de données peut exister différents schémas, un par module EJB, y accéder via jta-data-source

(Déployé dans Glassfish 4)

1
Juan Rodriguez