Подтвердить что ты не робот

JPA 2.0: добавление классов объектов в PersistenceUnit * из разных jar * автоматически

У меня есть Java-приложение на основе maven, основанное на CDI, которое имеет основной модуль и другие модули.
У ядра есть persistence.xml и некоторые объекты. Модули имеют дополнительные объекты.

Как я могу добавить объекты в центр внимания единицы персистентности?

Я прочитал руководство Hibernate, http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/configuration.html#setup-configuration-packaging

Я также видел эти вопросы SO

Я ищу решение, в котором Hibernate будет сканировать все загруженные классы, или, например, возьмет файл конфигурации из других банок (например, CDI делает с beans.xml).

В моем приложении не используется Spring. Я не настаиваю на мобильности - я буду придерживаться Hibernate.

  • Есть ли такое решение?
  • Есть ли способ создать PU из persistence.xml и добавить к нему классы программно?
  • Могу ли я добавить классы @Entity в EntityManagerFactory после его создания?

Обновление: я нашел в org.​hibernate.​ejb.​Ejb3Configuration:

public Ejb3Configuration configure(String persistenceUnitName, Map integration)  

http://docs.jboss.org/hibernate/entitymanager/3.6/javadocs/

4b9b3361

Ответ 1

Существует несколько способов решить эту проблему:

  • Как описано в Мне нужно <class> элементов в persistence.xml?, вы можете установить свойство hibernate.archive.autodetection, а Hibernate должен иметь возможность искать все аннотированные классы из classpath. Однако это не соответствует спецификации JPA.

  • Если вы используете Spring, от Spring 3.1.2 (или, возможно, даже немного раньше), в LocalContainerEntityManagerFactoryBean вы можете определить packageToScan, который будет запрашивать LocalContainerEntityManagerFactoryBean для сканирования в classpath для поиска всех аннотированных классов. Опять же, не соответствует спецификации JPA.

  • Я использовал Maven для создания инструментов. Годы раньше, я написал небольшой плагин, который будет генерировать persistence.xml во время процесса сборки. Плагин сканирует путь сборки, чтобы узнать все аннотированные классы и перечислить их в сгенерированном файле persistence.xml. Это очень утомительно, но результат соответствует спецификации JPA. Один недостаток (который не применяется к большинству людей, я считаю) - поиск происходит во время сборки, а не во время выполнения. Это означает, что если у вас есть приложение, для которого сущности JAR предоставляются только в момент развертывания/выполнения, но не время сборки, этот подход не будет работать.

Ответ 2

Ejb3Configuration была удалена в 4.3.0. Если вы не хотите создавать Hibernate Integrator, вы можете использовать свойство hibernate.ejb.loaded.classes.

properties.put(org.hibernate.jpa.AvailableSettings.LOADED_CLASSES, entities);
Persistence.createEntityManagerFactory("persistence-unit", properties);

Где entities - это List<Class> классов сущностей.

Ответ 3

У меня немного другая настройка, в которой я помещаю persistence.xml в файл WAR, но некоторые из его зависимостей включают в себя @Entity, аннотированный для включения в блок персистентности.

Я решил свою проблему, используя Maven, немного похожую на Adrian Shum, описанную в № 3, но используя этот элемент, чтобы включить банки для сканирования для аннотаций @Entity.

Я добавил свойство my-web/pom.xml для каждой зависимости, включая дополнительные объекты. Все мои банки являются частью мультипроектной сборки Maven, поэтому для меня это похоже.

<properties>
    <common.jar>common-${project.version}.jar</common.jar>
    <foo.jar>foo-${project.version}.jar</foo.jar>
</properties>

После этого добавьте следующее в файл persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" ... >
    <persistence-unit name="primary">
        <jta-data-source>java:jboss/datasources/mysource</jta-data-source>

        <jar-file>lib/${common.jar}</jar-file>
        <jar-file>lib/${foo.jar}</jar-file>

        ...
    </persistence-unit>
</persistence>

Наконец, я настраиваю maven-resource-plugin в web/pom.xml для замены выражений $в файле persistence.xml со свойствами, установленными в POM

<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
      <includes>
        <include>**/persistence.xml</include>
      </includes>
    </resource>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>false</filtering>
      <excludes>
        <exclude>**/persistence.xml</exclude>
      </excludes>
    </resource>
  </resources>
  ...
</build>

Ответ 4

У меня возникла одна и та же проблема, и, к сожалению, нет простого решения, похоже, что JPA не была разработана таким образом. Один из решений состоит в том, чтобы иметь только один persistence.xml для проекта (приложения) верхнего уровня. Это похоже на конфигурацию log4j. Persistence.xml должен перечислять все классы (используя <class>) или, если это не приложение Java SE, файлы jar (используя <jar-file>), которые используются приложением. Таким образом вы можете поместить объекты из нескольких модулей (банок) в единый блок непрерывности. Недостаток очевиден: вы должны перечислить все в одном файле.

EDIT: у меня есть (возможно) другое решение, которое использует файлы сопоставления XML, проверьте здесь: Несколько банок, одностановленное решение единицы измерения?

Ответ 5

Вы можете использовать эту концепцию: https://wiki.eclipse.org/Packaging_and_Deploying_EclipseLink_JPA_Applications_(ELUG)

<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
   <persistence-unit name="mamcaPU" transaction-type="JTA">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>mamcaPU</jta-data-source>
        <mapping-file>/META-INF/common-layer-mappings.xml</mapping-file>
    </persistence-unit>
</persistence>

общий слой-mappings.xml

<entity-mappings>   
   <entity class="vub.be.mamca.entity.Surveyactorgrouptable"></entity>
   <entity class="vub.be.mamca.entity.Userevaluationelicitationtable"></entity>
   <entity class="vub.be.mamca.entity.Userevaluationtable"></entity>
   <entity class="vub.be.mamca.entity.Usertable"></entity>
   <entity class="vub.be.mamca.entity.Userweightelicitationtable"></entity>
</entity-mappings>

Ответ 6

Возможный дубликат, см. мой вопрос SO.

Мы столкнулись с той же проблемой, и единственным способом, который мы нашли, было накопление всех объектов в одном файле persistence.xml для окончательного (веб-приложения).

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

Ответ 7

У меня есть аналогичная проблема, и решил ее с Hibernate Integrator SPI:

@Override
public void integrate(Configuration configuration,
    SessionFactoryImplementor sessionFactory,
    SessionFactoryServiceRegistry serviceRegistry) {

    configuration.addAnnotatedClass(MyEntity.class);
    configuration.buildMappings();
}

Интегратор предоставляется как служба Java.

Ответ 8

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

<jar-file></jar-file>

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