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



Answers

Dans l'environnement Java SE, par spécification, 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 les environnements Java SE pour assurer la portabilité

et

S'il n'est pas prévu que les classes de persistance annotées contenues dans la racine de l'unité de persistance soient incluses dans l'unité de persistance, l'élément exclude-unlisted-classes doit être utilisé. 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 n'avez pas besoin de le faire car le fournisseur analyse les annotations pour vous.

Officieusement, vous pouvez essayer de définir <exclude-unlisted-classes>false</exclude-unlisted-classes> dans votre fichier persistence.xml. Ce paramètre par défaut est false dans EE et true dans SE. EclipseLink et Toplink supportent autant que je peux dire. Mais vous ne devriez pas compter sur le fait de travailler dans SE, selon les 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>
Question

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 lorsque je supprime <class> éléments <class> , l'application ne voit pas les entités (toutes les classes sont annotées avec @Entity ).

Existe-t-il un mécanisme automatique pour analyser les classes @Entity ?




Hibernate ne prend pas en charge <exclude-unlisted-classes>false</exclude-unlisted-classes> sous SE, (une autre affiche mentionnant que cela fonctionne avec TopLink et EclipseLink).

Il existe des outils qui généreront automatiquement la liste des classes dans persistence.xml, par exemple l'assistant Import Database Schema dans IntelliJ. Une fois que vous avez les classes initiales de votre projet dans persistence.xml, il devrait être simple d'ajouter / supprimer des classes individuelles à la main pendant que votre projet progresse.




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

Je voulais importer cet artefact contenant la source java et lancer hibernate sur toutes les classes de mon pot d'artefacts "base-model" et ne pas les spécifier explicitement. Im ajoutant «base-model» comme une dépendance pour mon composant hibernate mais le problème est la balise dans persistence.xml vous permet seulement de spécifier des chemins absolus.

La façon dont je l'ai contourné est de copier ma dépendance jar «modèle de base» explicitement à mon répertoire cible et également dépouiller la version de celui-ci. Donc, si je construis mon artefact "base-model", il génère "base-model-1.0-SNAPSHOT.jar", l'étape copy-resources le copie comme "base-model.jar".

Donc dans votre pom pour le composant hibernate:

            <!-- 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 "process-classes":

            <!-- 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 mon persistence.xml je peux définir explicitement l'emplacement du pot ainsi:

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

et ajoutez la propriété:

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



Je ne suis pas sûr que cette solution est sous la spécification mais je pense que je peux partager pour les autres.

arbre de dépendance

mon-entities.jar

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

mon-services.jar

Cela dépend de my-entities . Contient uniquement des EJB.

mon-resources.jar

Cela dépend de my-services . Contient des classes de ressources et META-INF/persistence.xml .

problèmes

  • Comment pouvons-nous spécifier l'élément <jar-file/> dans my-resources comme le nom d'artefact version-postfixed d'une dépendance transitoire?
  • Comment pouvons-nous synchroniser la valeur de l'élément <jar-file/> et celle de la dépendance transitoire?

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 pour ê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>

Maven Enforcer Plugin

Avec la règle dependencyConvergence , nous pouvons assurer que la version de my-entities est identique à la fois 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>



Pour ceux qui exécutent JPA au printemps, à partir de la version 3.1, vous pouvez définir la propriété packagesToScan sous LocalContainerEntityManagerFactoryBean et supprimer définitivement persistence.xml.

Voici le bas-bas




Related