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?
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>
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 true
in 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>
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.
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.
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.
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>
pour JPA 2+ cela fait l'affaire
<jar-file></jar-file>
balaie tous les pots en guerre pour les classes @Entity annotées
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"/>
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.
Je ne suis pas sûr que cette solution soit conforme aux spécifications, mais je pense pouvoir partager pour les autres.
Contient uniquement des classes d'entités. Non META-INF/persistence.xml
.
Dépend de my-entities
. Contient des EJB uniquement.
Dépend de my-services
. Contient les classes de ressources et META-INF/persistence.xml
.
<jar-file/>
Dans my-resources
En tant que nom d'artefact version postfixée d'une dépendance transitoire?<jar-file/>
Et celle de la dépendance transitoire réelle?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>
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>
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"/>