Нужны ли мне элементы <class> в файле persistence.xml?

У меня очень простой файл 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?

Ответ 1

У persistence.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 явно называет управляемые классы персистентности.

В случае Hibernate посмотрите Chapter2. Настройка и настройка для более подробной информации.

РЕДАКТИРОВАТЬ: На самом деле, если вы не возражаете против того, чтобы не соответствовать спецификации, 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>

Ответ 2

В среде Java SE по спецификации вам необходимо указать все классы, как вы это делали:

Список всех названных управляемых классов персистентности должен быть указан в средах Java SE для обеспечения переносимости

и

Если не предполагается, что аннотированные классы персистентности, содержащиеся в корневом модуле персистентности, должны быть включены в блок персистентности, следует использовать элемент exclude-unlisted-classes. Элемент exclude-unlisted-classes не предназначен для использования в средах Java SE.

(JSR-000220 6.2.1.6)

В средах Java EE вам не нужно, поскольку поставщик сканирует аннотации для вас.

Неофициально вы можете установить <exclude-unlisted-classes>false</exclude-unlisted-classes> в свой файл persistence.xml. Этот параметр по умолчанию равен false в EE и true в SE. Оба EclipseLink и Toplink поддерживают это как можно дальше Я могу сказать. Но вы не должны полагаться на это, работая в SE, согласно спецификации, как указано выше.

Вы можете ПОПРОСИТЬ следующее (может или не может работать в средах 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>

Ответ 3

Нужны ли элементы класса в файле persistence.xml?

Нет, вы не обязательно. Вот как вы это делаете в Eclipse (Кеплер):

Щелкните правой кнопкой мыши по проекту, нажмите Свойства, выберите JPA, в Управление классом устойчивости отметьте Автоматически открывать аннотированные классы.

enter image description here

Ответ 4

Для тех, кто использует JPA в Spring, начиная с версии 3.1, вы можете установить свойство packagesToScan в LocalContainerEntityManagerFactoryBean и вообще избавиться от persistence.xml.

Здесь внизу

Ответ 5

для JPA 2+ это трюк

 <jar-file></jar-file>

сканировать все банки в войне для аннотированных классов @Entity

Ответ 6

Hibernate не поддерживает <exclude-unlisted-classes>false</exclude-unlisted-classes> под SE, (еще один плакат, упомянутый выше, работает с TopLink и EclipseLink).

Есть инструменты, которые автоматически генерируют список классов в persistence.xml, например. мастера импорта базы данных базы данных в IntelliJ. Когда у вас есть начальные классы вашего проекта в файле persistence.xml, должно быть просто добавить/удалить отдельные классы вручную по мере продвижения вашего проекта.

Ответ 7

Вы можете указать путь элемента jar-file к папке с скомпилированными классами. Например, я добавил что-то подобное, когда я подготовил persistence.xml к некоторым интеграционным тестам:

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

Ответ 8

Не уверен, что вы делаете что-то похожее на то, что я делаю, но Im генерирует нагрузку исходной java из XSD, используя JAXB в отдельном компоненте с использованием Maven. Допустим, этот артефакт называется "базовой моделью"

Мне захотелось импортировать этот артефакт, содержащий источник java, и запустить спящий режим для всех классов в банке артефакта "базовая модель" и не указывать каждый явно. Я добавляю "базовую модель" в качестве зависимости для моего спящего компонента, но проблема заключается в теге в persistence.xml, который позволяет вам указывать абсолютные пути.

То, как я обошел это, заключается в том, чтобы явным образом копировать свою зависимость jar базовой модели в мой целевой каталог, а также лишать его версию. Итак, если я создаю артефакт "базовой модели", он генерирует "base-model-1.0-SNAPSHOT.jar", шаг копирования-ресурсов копирует его как "base-model.jar".

Итак, в вашем pom для спящего компонента:

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

Затем я вызываю плагин hibernate в следующей фазе "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>

и, наконец, в моем persistence.xml я могу явно указать местоположение баночки таким образом:

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

и добавьте свойство:

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

Ответ 9

Это не решение, а подсказка для тех, кто использует Spring:

Я попытался использовать org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean с настройкой persistenceXmlLocation, но с этим я должен был предоставить элементы <class> (даже если persistenceXmlLocation просто указал на META-INF/persistence.xml).

Когда не с помощью persistenceXmlLocation, я могу опустить эти элементы <class>.

Ответ 10

Я не уверен, что это решение находится под спецификацией, но я думаю, что могу поделиться другими.

Дерево зависимостей

мой-entities.jar

Содержит только классы объектов. Нет META-INF/persistence.xml.

мой-services.jar

Зависит от my-entities. Содержит только EJB.

мой-resources.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>

Ответ 11

Не обязательно во всех случаях.

Я использую Jboss 7.0.8 и Eclipselink 2.7.0. В моем случае для загрузки сущностей без добавления их в persistence.xml я добавил следующее системное свойство в автономный XML файл Jboss:

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