web-dev-qa-db-fra.com

Ai-je besoin d'éléments <class> dans persistence.xml?

J'ai un fichier persistance.xml très simple:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
    xmlns="http://Java.Sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://Java.Sun.com/xml/ns/persistence http://Java.Sun.com/xml/ns/persistence/persistence_1_0.xsd">

    <persistence-unit name="eventractor" transaction-type="RESOURCE_LOCAL">
        <class>pl.michalmech.eventractor.domain.User</class>
        <class>pl.michalmech.eventractor.domain.Address</class>
        <class>pl.michalmech.eventractor.domain.City</class>
        <class>pl.michalmech.eventractor.domain.Country</class>

        <properties>
            <property name="hibernate.hbm2ddl.auto" value="validate" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>

</persistence>

et il fonctionne.

Mais quand je supprime <class> Les éléments de l'application ne voient pas les entités (toutes les classes sont annotées avec @Entity).

Existe-t-il un mécanisme automatique pour rechercher @Entity Des classes?

106
Michał Mech

Le fichier persistence.xml a un jar-file Que vous pouvez utiliser. De le Java EE 5) :

<persistence>
    <persistence-unit name="OrderManagement">
        <description>This unit manages orders and customers.
            It does not rely on any vendor-specific features and can
            therefore be deployed to any persistence provider.
        </description>
        <jta-data-source>jdbc/MyOrderDB</jta-data-source>
        <jar-file>MyOrderApp.jar</jar-file>
        <class>com.widgets.Order</class>
        <class>com.widgets.Customer</class>
    </persistence-unit>
</persistence>

Ce fichier définit une unité de persistance nommée OrderManagement, qui utilise une source de données compatible JTA jdbc/MyOrderDB. Les éléments jar-file Et class spécifient les classes de persistance gérées: classes d'entité, classes incorporables et superclasses mappées. L'élément jar-file Spécifie les fichiers JAR visibles de l'unité de persistance empaquetée contenant les classes de persistance gérées, tandis que l'élément class désigne explicitement les classes de persistance gérées.

Dans le cas d'Hibernate, jetez un œil à Chapitre2. Installation et configuration pour plus de détails.

EDIT: En fait, si cela ne vous dérange pas de ne pas être conforme aux spécifications, Hibernate prend en charge la détection automatique même en Java Pour ce faire, ajoutez la propriété hibernate.archive.autodetection:

<persistence-unit name="eventractor" transaction-type="RESOURCE_LOCAL">
  <!-- This is required to be spec compliant, Hibernate however supports
       auto-detection even in JSE.
  <class>pl.michalmech.eventractor.domain.User</class>
  <class>pl.michalmech.eventractor.domain.Address</class>
  <class>pl.michalmech.eventractor.domain.City</class>
  <class>pl.michalmech.eventractor.domain.Country</class>
   -->

  <properties>
    <!-- Scan for annotated classes and Hibernate mapping XML files -->
    <property name="hibernate.archive.autodetection" value="class, hbm"/>

    <property name="hibernate.hbm2ddl.auto" value="validate" />
    <property name="hibernate.show_sql" value="true" />
  </properties>
</persistence-unit>
78
Pascal Thivent

Dans environnement Java SE, vous devez spécifier toutes les classes comme vous l'avez fait:

Une liste de toutes les classes de persistance gérées nommées doit être spécifiée dans Java SE pour assurer la portabilité

et

Si vous ne souhaitez pas que les classes de persistance annotées contenues dans la racine de l'unité de persistance soient incluses dans l'unité de persistance, vous devez utiliser l'élément exclude-unlisted-classes. L'élément exclude-unlisted-classes n'est pas destiné à être utilisé dans les environnements Java SE.

(JSR-000220 6.2.1.6)

Dans les environnements Java EE , vous ne devez pas procéder ainsi car le fournisseur recherche les annotations à votre place.

De manière officieuse, vous pouvez essayer de définir <exclude-unlisted-classes>false</exclude-unlisted-classes> dans votre persistence.xml. La valeur par défaut de ce paramètre est false dans EE et truein SE. Les deux EclipseLink et Toplink le supporte autant que je peux le dire. Mais vous ne devriez pas vous fier à ce qu'il fonctionne en SE, conformément aux spécifications, comme indiqué ci-dessus.

Vous pouvez essayer ce qui suit (peut ou peut ne pas fonctionner dans les environnements SE):

<persistence-unit name="eventractor" transaction-type="RESOURCE_LOCAL">
     <exclude-unlisted-classes>false</exclude-unlisted-classes>

    <properties>
            <property name="hibernate.hbm2ddl.auto" value="validate" />
            <property name="hibernate.show_sql" value="true" />
    </properties>
</persistence-unit>
43
Mads Mobæk

Ai-je besoin d'éléments de classe dans persistence.xml?

Non, pas nécessairement. Voici comment vous le faites dans Eclipse (testé par Kepler):

Faites un clic droit sur le projet, cliquez sur Propriétés, sélectionnez JPA , dans le Gestion de classe de persistance tick - Découvrez les classes annotées automatiquement.

enter image description here

13
abbas

Pour ceux qui exécutent JPA dans Spring, à partir de la version 3.1, vous pouvez définir la propriété packagesToScan sous LocalContainerEntityManagerFactoryBean et vous débarrasser de persistence.xml.

Voici le bas-bas

11
Christopher Yang

Hibernate ne supporte pas <exclude-unlisted-classes>false</exclude-unlisted-classes> sous SE (une autre affiche indique que cela fonctionne avec TopLink et EclipseLink).

Certains outils généreront automatiquement la liste des classes dans persistence.xml, par exemple. l'assistant d'importation de schéma de base de données dans IntelliJ. Une fois que vous avez défini les classes initiales de votre projet dans persistence.xml, il devrait être simple d’ajouter ou de supprimer manuellement des classes individuelles au fur et à mesure de la progression du projet.

7
Chuck Stephanski

Vous pouvez prévoir pour jar-file chemin d’élément vers un dossier avec des classes compilées. Par exemple, j'ai ajouté quelque chose comme ça lorsque j'ai préparé persistence.xml à certains tests d'intégration:

 <jar-file>file:../target/classes</jar-file>
7
Arek Trzepacz

pour JPA 2+ cela fait l'affaire

 <jar-file></jar-file>

balaie tous les pots en guerre pour les classes @Entity annotées

7
eriskooo

Je ne sais pas si vous faites quelque chose de similaire à ce que je fais, mais je génère une charge de source Java à partir d'un XSD utilisant JAXB dans un composant séparé utilisant Maven. Disons que cet artefact s'appelle "modèle de base"

Je voulais importer cet artefact contenant la source Java et exécuter l'hibernation sur toutes les classes de mon fichier jar d'artefact "modèle de base" et ne pas les spécifier explicitement. Je suis en train d'ajouter le modèle de base comme dépendance. pour mon composant hibernate mais le problème est que la balise dans persistence.xml ne vous permet que de spécifier des chemins absolus.

La façon dont je l’ai contournée est de copier ma dépendance de jar "modèle de base" de manière explicite dans mon répertoire cible et également de supprimer la version de celle-ci. Ainsi, alors que si je construis mon artefact "modèle de base", il génère "base-modèle-1.0-SNAPSHOT.jar", l'étape de copie des ressources le copie en tant que "base-modèle.jar".

Donc, dans votre pom pour le composant d'hibernation:

            <!-- We want to copy across all our artifacts containing Java code
        generated from our scheams. We copy them across and strip the version
        so that our persistence.xml can reference them directly in the tag
        <jar-file>target/dependency/${artifactId}.jar</jar-file> -->
        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.5.1</version>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                </execution>
            </executions>       
            <configuration>
                <includeArtifactIds>base-model</includeArtifactIds>
                <stripVersion>true</stripVersion>
            </configuration>        
        </plugin>

Ensuite, j'appelle le plugin hibernate dans la phase suivante "classes de processus":

            <!-- Generate the schema DDL -->
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>hibernate3-maven-plugin</artifactId>
            <version>2.2</version>

            <executions>
                <execution>
                    <id>generate-ddl</id>
                    <phase>process-classes</phase>
                    <goals>
                        <goal>hbm2ddl</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <components>
                    <component>
                        <name>hbm2Java</name>
                        <implementation>annotationconfiguration</implementation>
                        <outputDirectory>/src/main/Java</outputDirectory>
                    </component>
                </components>
                <componentProperties>
                    <persistenceunit>mysql</persistenceunit>
                    <implementation>jpaconfiguration</implementation>
                    <create>true</create>
                    <export>false</export>
                    <drop>true</drop>
                    <outputfilename>mysql-schema.sql</outputfilename>
                </componentProperties>
            </configuration>
        </plugin>

et enfin dans persistence.xml, je peux explicitement définir l'emplacement du fichier jar de la manière suivante:

<jar-file>target/dependency/base-model.jar</jar-file>

et ajoutez la propriété:

<property name="hibernate.archive.autodetection" value="class, hbm"/>
4
Spencer Loveridge

Ce n'est pas une solution mais un indice pour ceux qui utilisent Spring:

J'ai essayé d'utiliser org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean avec le paramètre persistenceXmlLocation mais avec cela je devais fournir le <class> éléments (même si le persistenceXmlLocation vient de pointer sur META-INF/persistence.xml).

Quand pas en utilisant persistenceXmlLocation je pourrais omettre ces <class> éléments.

3
Ethan Leroy

Je ne suis pas sûr que cette solution soit conforme aux spécifications, mais je pense pouvoir partager pour les autres.

arbre de dépendance

mon-entités.jar

Contient uniquement des classes d'entités. Non META-INF/persistence.xml.

my-services.jar

Dépend de my-entities. Contient des EJB uniquement.

mes-ressources.jar

Dépend de my-services. Contient les classes de ressources et META-INF/persistence.xml.

problèmes

  • Comment pouvons-nous spécifier l'élément <jar-file/> Dans my-resources En tant que nom d'artefact version postfixée d'une dépendance transitoire?
  • Comment synchroniser la valeur de l'élément <jar-file/> Et celle de la dépendance transitoire réelle?

solution

dépendance directe (redondante?) et filtrage des ressources

Je mets une propriété et une dépendance dans my-resources/pom.xml.

<properties>
  <my-entities.version>x.y.z-SNAPSHOT</my-entities.version>
</properties>
<dependencies>
  <dependency>
    <!-- this is actually a transitive dependency -->
    <groupId>...</groupId>
    <artifactId>my-entities</artifactId>
    <version>${my-entities.version}</version>
    <scope>compile</scope> <!-- other values won't work -->
  </dependency>
  <dependency>
    <groupId>...</groupId>
    <artifactId>my-services</artifactId>
    <version>some.very.sepecific</version>
    <scope>compile</scope>
  </dependency>
<dependencies>

Maintenant, préparez le persistence.xml Prêt à être filtré

<?xml version="1.0" encoding="UTF-8"?>
<persistence ...>
  <persistence-unit name="myPU" transaction-type="JTA">
    ...
    <jar-file>lib/my-entities-${my-entities.version}.jar</jar-file>
    ...
  </persistence-unit>
</persistence>

Plugin Maven Enforcer

Avec la règle dependencyConvergence, nous pouvons nous assurer que la version my-entities 'Est la même en direct et en transitif.

<plugin>
  <groupId>org.Apache.maven.plugins</groupId>
  <artifactId>maven-enforcer-plugin</artifactId>
  <version>1.4.1</version>
  <executions>
    <execution>
      <id>enforce</id>
      <configuration>
        <rules>
           <dependencyConvergence/>
        </rules>
      </configuration>
      <goals>
        <goal>enforce</goal>
      </goals>
    </execution>
  </executions>
</plugin>
2
Jin Kwon

Pas nécessairement dans tous les cas.

J'utilise Jboss 7.0.8 et Eclipselink 2.7.0. Dans mon cas, pour charger des entités sans ajouter la même chose dans persistence.xml, j'ai ajouté la propriété système suivante dans Jboss Standalone XML:

<property name="eclipselink.archive.factory" value="org.jipijapa.eclipselink.JBossArchiveFactoryImpl"/>

0
Gandhi