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/
Ответы
Ответ 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