Чи потрібні <class> елементи в persistent.xml?


110

У мене дуже простий файл persistance.xml:

<?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>

і це працює.

Але коли я видаляю <class>елементи, додаток не бачить сутностей (усі класи помічені за допомогою @Entity).

Чи є якийсь автоматичний механізм сканування @Entityкласів?

Відповіді:


78

У persistent.xml є jar-fileте, що ви можете використовувати. З навчального посібника 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>

Цей файл визначає одиницю збереження OrderManagement, яка використовується джерелом даних JTA jdbc/MyOrderDB. Елементи jar-fileта classелементи задають керовані класи стійкості: класи сутностей, класи, що вбудовуються, та накреслені суперкласи. В jar-fileелементі визначає файли JAR, які видно упакована інерційність одиниці , які містять керовану збереження класів, в той час як classелемент явно імена вдалися живучість класів.

У випадку зі сплячим світом подивіться Розділ2. Також налаштування та конфігурація для отримання детальної інформації.

EDIT: Насправді, якщо ви не заперечуєте, щоб не відповідали технічним характеристикам, Hibernate підтримує автоматичне виявлення навіть у Java SE. Для цього додайте 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>

13
Я бачу, але сутності (@Entity) знаходяться в окремому проекті Maven, тому ім'я jar-файлу може змінюватися в кожній збірці. Я шукаю щось для того, щоб сканувати все у певному пакеті чи classpath. Мені просто лінь вводити багато, багато елементів <class> у файл persistent.xml.
Michał Mech

На кожній збірці ?! Навіть не запитую, чому, але ... ви можете використати фільтрацію для вирішення цього питання.
Паскаль Thivent

Не всі точно, але я хочу бути стійкими до змін.
Michał Mech

5
Я знаю древню нитку, але подивіться на плагін jpa-maven .
Laird Nelson

Ви можете використовувати елемент <mapping-file> (який містить перелік об'єктів) у persistent.xml, щоб ви могли зберегти те саме ім'я використаних файлів та інтегрувати їх у збірку згаданих банок.
med_alpa

44

У середовищі Java SE за специфікацією ви повинні вказати всі класи , які ви зробили:

У середовищі Java SE необхідно вказати список усіх названих керованих класів стійкості, щоб забезпечити переносимість

і

Якщо не передбачається включення анотованих класів стійкості, що містяться в корені одиниці стійкості, до одиниці збереження, слід використовувати елемент класів виключення, який не міститься у списку. Елемент класів виключення, який не міститься в списку, не призначений для використання в середовищах Java SE.

(JSR-000220 6.2.1.6)

У середовищах Java EE вам не доведеться цього робити, оскільки постачальник сканує для вас примітки.

Неофіційно ви можете спробувати встановити <exclude-unlisted-classes>false</exclude-unlisted-classes>ваш persistent.xml. Цей параметр за замовчуванням до falseEE та trueSE. І EclipseLink, і Toplink підтримують це, наскільки я можу сказати. Але вам не слід покладатися на це, працюючи в ДП, відповідно до специфікації, як зазначено вище.

Ви можете ВИМОЖИТИ наступне (може бути, а може і не працювати в 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>

2
<exclude-unlisted-classes>false</exclude-unlisted-classes>не працював з WildFly 8.2.1.Final + Hibernate 4.3.7
Андреас Дітріх

12

Чи потрібні мені елементи класу в persistent.xml?

Ні, вам не обов'язково. Ось як ви це робите в Eclipse (протестований Kepler):

Клацніть правою кнопкою миші по об'єкту, натисніть кнопку Властивості , виберіть JPA , в управлінні класом Persistence кліщ Discover автоматично анотований класи .

введіть тут опис зображення


9
Чому виступають? ОП навіть не згадує Eclipse, і ця відповідь не показує, що ця функція Eclipse робить під кришкою, щоб можна було зробити це без IDE.
Артем Новіков

2
@ Артем Новіков: Я вважаю це суворим, оскільки часто виникає питання в різних умовах, і тут ми хочемо допомогти або дати корисні підказки! (як для мене) Це корисно, оскільки Eclipse є загальним IDE для такого розвитку, і під кришкою не так важливо, але я думаю, що він буде включати всі відповідні проекти робочої області (наприклад, мій проект залежить від цього).
Андреас Дітріх

stackoverflow.com/questions/17951297/… приємний трюк, але, мабуть, він працює лише в тому випадку, якщо об'єкти потрапляють у той самий клас завантажувачів, що і persistent.xml
Pierluigi Vernetto

@abbas Будь ласка, покажіть, persistence.xmlщо породжує Eclipse.
Франс

12

Для тих, хто працює з JPA навесні, починаючи з версії 3.1, ви можете встановити packagesToScanвластивість під LocalContainerEntityManagerFactoryBeanі повністю позбутися від persistent.xml.

Ось низький низ


Працювали для мене! Сценарій - весна 4 + сплячка + jpa2 + maven. Тестування JUnit не знайшло моїх сутностей, але за допомогою цього налаштування воно зробило свою роботу.
СБА

8

Ви можете надати jar-fileшлях елементів до папки зі складеними класами. Наприклад, я додав щось подібне, коли я готував persistent.xml до деяких інтеграційних тестів:

 <jar-file>file:../target/classes</jar-file>

Це те, що я шукав!
xtian

Працює і з EclipseLink!
Бомби

8

для JPA 2+ це робить трюк

 <jar-file></jar-file>

сканувати всі банки на війні на предмет приміток на класи @Entity


2
у вас є додаткова інформація про це? чи працює це випадково чи написано в специфікації? Це залежить від реалізації?
Маркус

сканер в класі розширює AbstractScannerImpl, у сплячому режимі - не маю уявлення, чи це помилка чи функція, вибачте
eriskooo

1
У Java SE з Hibernate 5.1.2.Корінно, це рішення не працює. Hibernate очікує імені файлу jar ( java.lang.IllegalArgumentException: Unable to visit JAR file:).
Стефан

1
працює! :) з WildFly 8.2.1.Final + Hibernate 4.3.7.Final
Andreas Dietrich

Thx людина, багато шукав, і це найновіше рішення. Wildfly10 + Hibernate 5.0.7 працює.
бутта

7

Hibernate не підтримує <exclude-unlisted-classes>false</exclude-unlisted-classes>SE, (інший плакат згадував, що це працює з TopLink та EclipseLink).

Є інструменти, які автоматично генерують список класів до persistent.xml, наприклад, майстер схеми імпортування баз даних в IntelliJ. Після того, як ви отримаєте початкові класи вашого проекту в persistent.xml, додавати / видаляти окремі класи вручну слід по мірі прогресування проекту.


Автоматичне виявлення сутностей у Java SE просто не є частиною JPA. Програми, що покладаються на це, не є портативними.
Паскаль Thivent

4

Не впевнений, чи ви робите щось подібне до того, що я роблю, але я створюю навантаження вихідної Java з XSD за допомогою JAXB в окремий компонент за допомогою Maven. Скажімо, цей артефакт називають "базовою моделлю"

Я хотів імпортувати цей артефакт, що містить джерело java, і перейти у сплячий режим над усіма класами в моїй базі артефактів «базової моделі», а не вказувати їх явно. Я додаю "базову модель" як залежність від мого сплячого компонента, але проблема полягає в тезі в persistent.xml дозволяє лише вказати абсолютні шляхи.

Те, як я її обійшов, - це скопіювати мою залежність від «базової моделі» відверто до мого цільового режиму, а також зняти її версію. Тож якщо я будую артефакт "базової моделі", він генерує "base-model-1.0-SNAPSHOT.jar", крок "copy-resources" копіює його як "base-model.jar".

Тож у твоєму значенні щодо сплячого компонента:

            <!-- 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>

Тоді я називаю плагін у сплячому режимі на наступній фазі "процеси-класи":

            <!-- 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>

і, нарешті, в моїй persistent.xml я можу явно встановити розташування банку таким чином:

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

і додайте властивість:

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

3

Це не рішення, а підказка для тих, хто використовує Spring:

Я намагався використовувати org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBeanз налаштуваннями, persistenceXmlLocationале з цим мені довелося надати <class>елементи (навіть якщо persistenceXmlLocationтільки що вказали META-INF/persistence.xml).

Якщо я не використовую, persistenceXmlLocationя міг опустити ці <class>елементи.


Я використовував persistenceXmlLocationвластивість у своїх LocalContainerEntityManagerFactoryBeanналаштуваннях. Але всі запити працюють, навіть якщо я опускаю <class>елементи. Це за допомогою програми Spring / Hibernate / Maven. Але ви натякаєте, що ви говорите, що "не використовуючи persistentXmlLocation, я міг опустити ці елементи <class>." але для мене це навпаки.
Пощастило

@Якщо ви праві, тому що persistentXmlLocation замінює пакетиToScan - якщо ви шукаєте джерела. Тому не використовуйте його під час використання пакетиToScan.
Артем Новіков

2

Я не впевнений, що це рішення під специфікацією, але я думаю, що можу поділитися з іншими.

дерево залежності

мій-сутності.jar

Містить лише об'єкти класи. Ні META-INF/persistence.xml.

my-services.jar

Залежить від my-entities. Містить лише EJB.

мій-ресурси.jar

Залежить від my-services. Містить ресурси та класи META-INF/persistence.xml.

проблеми

  • Як ми можемо вказати <jar-file/>елемент my-resourcesяк назву артефакту з постфіксованою версією перехідної залежності?
  • Як ми можемо синхронізувати значення <jar-file/>елемента та фактичну перехідну залежність?

рішення

пряма (зайва?) залежність та фільтрація ресурсів

Я поклав властивість і залежність в 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>

Тепер persistence.xmlприготуйтеся до фільтрування

<?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

За допомогою dependencyConvergenceправила ми можемо запевнити, що my-entitiesверсія 'однакова і в прямій, і в перехідній.

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

0

Не обов’язково у всіх випадках.

Я використовую Jboss 7.0.8 та Eclipselink 2.7.0. У моєму випадку для завантаження об'єктів без додавання того ж у persistent.xml я додав у Jboss Standalone XML таке системне властивість:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.