JPA 2.0:自动将实体类从不同的jar添加到PersistenceUnit中

38
我有一个基于CDI的Java SE应用程序,使用Maven构建,其中包括一个核心模块和其他模块。 核心模块有"persistence.xml"和一些实体类。 其他模块有额外的实体类。
如何将这些实体类添加到持久化单元的聚光灯中?
我已经阅读了Hibernate手册,http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/configuration.html#setup-configuration-packaging 我也看到了这些SO问题: 我正在寻找一种解决方案,其中Hibernate会扫描所有加载的类,或者会从其他JAR文件中获取某些配置文件(例如CDI使用的"beans.xml")。
我的应用程序不使用Spring。 我不要求可移植性 - 我将坚持使用Hibernate。
  • 有这样的解决方案吗?
  • 是否有一种方法可以从persistence.xml创建PU并以编程方式添加类?
  • 在创建了EntityManagerFactory之后,我可以将@Entity类添加到其中吗?

更新:我在org.hibernate.ejb.Ejb3Configuration中找到了:

public Ejb3Configuration configure(String persistenceUnitName, Map integration)  

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


也许这可能是一个解决方案:https://dev59.com/6WUp5IYBdhLWcg3wz58H - Adam Dyga
8个回答

11
有几种解决方法:
  1. Do I need <class> elements in persistence.xml?所述,您可以设置hibernate.archive.autodetection属性,Hibernate应该能够从类路径中查找所有带注释的类。但是,这不符合JPA规范。

  2. 如果您正在使用Spring,从Spring 3.1.2(或可能稍早)开始,在LocalContainerEntityManagerFactoryBean中,您可以定义packageToScan,它将要求LocalContainerEntityManagerFactoryBean在类路径中扫描以查找所有带注释的类。同样,这也不符合JPA规范。

  3. 我使用Maven作为构建工具。多年前,我编写了一个小插件,在构建过程中生成persistence.xml。该插件将从构建类路径中扫描以找出所有已注释的类,并在生成的persistence.xml中列出它们。这最费力,但结果符合JPA规范。一个缺点(我认为大多数人不会遇到)是查找发生在构建时而不是运行时。这意味着,如果您有一个应用程序,其中实体JAR仅在部署/运行时提供而不是构建时,这种方法将不起作用。


对于第三点,似乎有人已经制作了类似的公开可用工具:https://github.com/ljnelson/jpa-maven-plugin - Adrian Shum
1
对于第二点,您需要禁用通常在LocalContainerEntityManagerFactoryBean中配置的persistenceUnit。也就是说,如果指定了persistenceUnit,则Spring将忽略packageToScan设置。 - Eric B.
这里有一个更新的 jpa-maven-plugin 分支:https://github.com/iSnow/jpa-maven-plugin - Johannes Jander

8

Ejb3Configuration在4.3.0中已被移除。如果您不想创建Hibernate的整合器,可以使用属性hibernate.ejb.loaded.classes

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

这里的entities是一个实体类的List<Class>


LOADED_CLASSES设置被标记为“仅供内部使用”,并且在使用Maven下载的jar包中未定义。 - VaclavC
嗨,我目前正在使用这个方法,让一个persistence.xml指向多个jar文件!不知道为什么它被删除了? - Mathias

6
我有一个略微不同的设置,我将persistence.xml放在WAR文件中,但其中一些依赖项包括@ Entity注释类以包含在持久性单元中。
我使用了Maven解决了我的问题,有点像Adrian Shum在#3中描述的方式,但是使用元素来扫描@Entity注释的jar。
我为每个包含额外实体的依赖项添加了一个属性到my-web/pom.xml。所有的jar都是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>

最后,我在web/pom.xml文件中配置了maven-resource-plugin插件,用POM中设置的属性替换persistence.xml中的$表达式。
<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>

3
我经历了同样的问题,但很遗憾没有简单的解决方案,基本上看起来JPA不是设计用于这种方式。其中一个解决方案是每个顶层项目(应用程序)只有一个persistence.xml。这有点类似于log4j配置。persistence.xml必须列出所有类(使用)或者如果它不是Java SE应用程序,则使用jar文件(使用)。这样,您可以将多个模块(jar)的实体放入单个持久性单元。缺点是显而易见的:您必须在一个文件中列出所有内容。
编辑:我已经(可能)发现了另一种解决方案,它使用XML映射文件,可以在这里查看:Multiple jars, single persistence unit solution?

1
你可以使用这个概念: 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>

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

0

可能是重复问题,请参见我的SO问题

我们遇到了同样的问题,唯一找到的方法是将所有实体累积在一个persistence.xml文件中,用于最终(Web)应用程序。

同时,我们在测试资源中定义单独的persistence.xml文件,以便可以按模块运行验收测试。


0

我有一个类似的问题,而且使用Hibernate的Integrator SPI 解决了它:

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

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

Integrator提供Java服务


-4

对于 JPA 2+,这个就行了

<jar-file></jar-file>

扫描WAR中所有的JAR文件,寻找带有@ Entity注释的类。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接