我是否需要persistence.xml中的<class>元素?


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类的机制?

Answers:


78

jar-file您可以使用persistence.xml 。从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-fileclass元素指定管持久类:实体类,可嵌入类和超类映射。该jar-file元素指定JAR文件都包含持久化类管理的打包持久单元可见,而该class元素明确命名持久化类管理。

对于Hibernate,请看第二章。也可以进行设置和配置以获取更多详细信息。

编辑:实际上,如果您不介意不符合规范,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文件名可以在每次构建时更改。我正在寻找可以扫描特定程序包或类路径中的所有内容的东西。我只是懒惰地在persistence.xml文件中键入很多<class>元素。
米哈尔机甲

在每个版本上?!我什至不问为什么,但是...您可以使用过滤来解决此问题。
Pascal Thivent 09年

并非所有人都可以,但是我想抵抗变化。
米哈尔机甲

5
我知道古代线程,但是看看jpa-maven-plugin
尼尔森·尼尔森

您可以在persistence.xml中使用<mapping-file>元素(包含实体列表),因此您可以保持使用文件的名称相同,并将它们集成到引用的jar的构建中。
med_alpa '16

44

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中进行设置。此参数默认为falseEE和true SE中。双方的EclipseLinkToplink的支持这是到目前为止,我可以告诉。但是,如上所述,根据规范,您不应该依赖它在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>

2
<exclude-unlisted-classes>false</exclude-unlisted-classes>不适用于WildFly 8.2.1.Final + Hibernate 4.3.7
Andreas Dietrich,2002年

12

我是否需要persistence.xml中的Class元素?

不,你不一定。这是在Eclipse中进行的方法(已测试过Kepler):

右键单击项目,单击“ 属性”,选择“ JPA”,在“ 持久性类管理”中,勾选“自动发现带注释的类”

在此处输入图片说明


9
为什么投票?OP甚至没有提到Eclipse,并且这个答案也没有显示Eclipse功能在幕后的作用,因此即使没有IDE也可以做到这一点。
Artem Novikov

2
@Artem Novikov:我觉得这很严厉,因为问题经常来自不同的环境,在这里我们想提供帮助或提供有用的提示!(对我来说如此)之所以有用,是因为Eclipse是像这样进行开发的通用IDE,并且在幕后并不是那么重要,但是我想它将包括所有相关的工作区项目(例如,我的项目取决于该项目)。
安德烈亚斯·迪特里希

stackoverflow.com/questions/17951297/…不错的技巧,但显然只有在实体与persistence.xml处于同一类加载器中时,它才有效
Pierluigi Vernetto

@abbas请显示persistence.xmlEclipse生成的。
弗朗斯

12

对于从Spring 3.1开始在Spring中运行JPA的用户,可以packagesToScan在下设置property LocalContainerEntityManagerFactoryBean并完全摆脱persistence.xml。

这是低点


为我工作!场景是spring 4 + hibernate + jpa2 + maven。JUnit测试找不到我的实体,但是通过此设置它可以完成任务。
2014年

8

您可以提供jar-file具有已编译类的文件夹的元素路径。例如,当我为一些集成测试准备persistence.xml时,我添加了类似的内容:

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

这就是我想要的!
xtian

也可以与EclipseLink一起使用!
孟买

8

对于JPA 2+,这可以解决问题

 <jar-file></jar-file>

扫描战争中的所有罐子以查找带注释的@Entity类


2
您是否有关于此的更多信息?这是偶然工作还是写在规范中?是否取决于实现?
markus

扫描程序在扩展AbstractScannerImpl的类中,处于休眠状态-不知道它是否是错误或功能,对不起
eriskooo 2015年

1
在带有Hibernate 5.1.2.Final的Java SE中,此解决方案不起作用。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正常工作。
boutta

7

Hibernate <exclude-unlisted-classes>false</exclude-unlisted-classes>在SE下不支持(另一个海报提到此功能可用于TopLink和EclipseLink)。

有一些工具可以将类列表自动生成为persistence.xml,例如IntelliJ中的“导入数据库模式”向导。在persistence.xml中获得项目的初始类后,随着项目的进行,手动添加/删除单个类应该很简单。


Java SE中的实体自动检测只是JPA的一部分。依赖于此的应用程序不可移植。
Pascal Thivent'9

4

不知道您是否正在执行与我正在执行的操作类似的操作,但是Im在使用Maven的单独组件中使用JAXB从XSD生成了源Java负载。可以说该工件称为“基本模型”

我想导入包含Java源代码的工件,并在“基本模型”工件jar中的所有类上运行休眠模式,而不是明确指定每个对象。我添加了“基本模型”作为我的休眠组件的依赖项,但麻烦的是persistence.xml中的标记仅允许您指定绝对路径。

我的解决方法是将我的“基本模型” jar依赖项明确复制到我的目标目录,然后剥离其版本。因此,如果我构建“基本模型”工件,则会生成“基本模型1.0-SNAPSHOT.jar”,而“复制资源”步骤会将其复制为“基本模型.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>

然后在下一阶段将“休眠类”称为“进程类”:

            <!-- 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的位置:

<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>元素。


persistenceXmlLocationLocalContainerEntityManagerFactoryBean设置中使用了属性。但是,即使我省略了所有<class>元素,所有查询仍然有效。它在Spring / Hibernate / Maven应用程序上。但是在提示中,您说“当不使用persistenceXmlLocation时,我可以省略这些<class>元素。” 但是反过来对我来说。
幸运

@Ethan是正确的,因为persistenceXmlLocation会覆盖packagesToScan-如果您查看源代码。因此,在使用packagesToScan时不要使用它。
阿特姆·诺维科夫

2

我不确定该解决方案是否符合规范,但我想可以与他人分享。

依赖树

my-entities.jar

仅包含实体类。没有META-INF/persistence.xml

my-services.jar

取决于my-entities。仅包含EJB。

my-resources.jar

取决于my-services。包含资源类和META-INF/persistence.xml

问题

  • 我们如何<jar-file/>my-resources瞬态依赖项的版本后缀工件名称中指定element ?
  • 我们如何同步<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。在装入实体而不在persistence.xml中添加实体的情况下,我在Jboss Standalone XML中添加了以下系统属性:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.