ChatGPT解决这个技术问题 Extra ChatGPT

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

我有非常简单的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 类?


A
Alexey Osetsky

persistence.xml 有一个可以使用的 jar-file。从 the Java EE 5 tutorial

这个单元管理订单和客户。它不依赖于任何供应商特定的功能,因此可以部署到任何持久性提供商。 jdbc/MyOrderDB MyOrderApp.jar com.widgets.Order com.widgets.Customer

该文件定义了一个名为 OrderManagement 的持久性单元,它使用 JTA 感知数据源 jdbc/MyOrderDBjar-fileclass 元素指定托管持久性类:实体类、可嵌入类和映射超类。 jar-file 元素指定对包含托管持久性类的打包持久性单元可见的 JAR 文件,而 class 元素显式命名托管持久性类。

对于 Hibernate,请查看 Chapter2. Setup and configuration 以了解更多详细信息。

编辑: 实际上,如果您不介意不符合规范,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>

我明白了,但是实体(@Entity)位于单独的 Maven 项目中,因此 jar 文件名可以在每次构建时更改。我正在寻找可以扫描特定包或类路径中的所有内容的东西。我只是懒得在persistence.xml 文件中输入很多很多 元素。
在每个版本上?!我什至不会问为什么,但是......你可以使用过滤来解决这个问题。
不是每个人都完全一样,但我想抵制变化。
古老的线程,我知道,但看看 jpa-maven-plugin
您可以在 persistence.xml 中使用 元素(其中包含实体列表),这样您就可以保留所用文件的相同名称并将它们集成到所引用 jar 的构建中。
r
rsavchenko

在 Java SE 环境中,您必须按照规范指定所有类:

必须在 Java SE 环境中指定所有命名的托管持久性类的列表以确保可移植性

如果不打算将包含在持久性单元根中的带注释的持久性类包含在持久性单元中,则应使用 exclude-unlisted-classes 元素。 exclude-unlisted-classes 元素不适用于 Java SE 环境。

(JSR-000220 6.2.1.6)

在 Java EE 环境中,您不必这样做,因为提供程序会为您扫描注释。

非正式地,您可以尝试在您的 persistence.xml 中设置 <exclude-unlisted-classes>false</exclude-unlisted-classes>。此参数在 EE 中默认为 false,在 SE 中默认为 true。据我所知,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>

<exclude-unlisted-classes>false</exclude-unlisted-classes> 不适用于 WildFly 8.2.1.Final + Hibernate 4.3.7
a
abbas

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

不,你不一定。以下是您在 Eclipse 中的操作方式(Kepler 测试):

右键项目,点击属性,选择JPA,在Persistence class management中勾选Discover annotated classes automatically。

https://i.stack.imgur.com/oODvB.png


为什么要投票? OP 甚至没有提到 Eclipse,而且这个答案也没有显示这个 Eclipse 特性在幕后做了什么,因此人们可以在没有 IDE 的情况下做到这一点。
@Artem Novikov:我觉得这很苛刻,因为问题通常来自不同的环境,在这里我们想提供帮助或提供有用的提示! (对我来说)它很有用,因为 Eclipse 是一个用于像这样进行开发的通用 IDE,并且在底层并不那么重要,但我想它将包括所有相关的工作区项目(例如,我的项目依赖于)。
stackoverflow.com/questions/17951297/… 不错的技巧,但显然它只有在实体最终位于与 persistence.xml 相同的类加载器中时才有效
@abbas 请显示 Eclipse 生成的 persistence.xml
l
lukas84

对于那些在 Spring 中运行 JPA,从 3.1 版开始,您可以在 LocalContainerEntityManagerFactoryBean 下设置 packagesToScan 属性并完全摆脱 persistence.xml。

Here's the low-down


为我工作!场景是spring 4 + hibernate + jpa2 + maven。 JUnit 测试没有找到我的实体,但是通过这个设置它完成了工作。
A
Arek Trzepacz

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

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

这就是我要找的!
也适用于 EclipseLink!
e
eriskooo

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

 <jar-file></jar-file>

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


你有更多关于这方面的信息吗?这是偶然工作还是写在规范中?它依赖于实现吗?
扫描仪在类扩展 AbstractScannerImpl,休眠 - 不知道它是错误还是功能,抱歉
在带有 Hibernate 5.1.2.Final 的 Java SE 中,此解决方案不起作用。 Hibernate 需要一个 jar 文件名 (java.lang.IllegalArgumentException: Unable to visit JAR file:)。
作品! :) 使用 WildFly 8.2.1.Final + Hibernate 4.3.7.Final
Thx man,搜索了很多,这是可用的最简洁的解决方案。 Wildfly10 + Hibernate 5.0.7 工作。
C
Chuck Stephanski

在 SE 下,Hibernate 不支持 <exclude-unlisted-classes>false</exclude-unlisted-classes>(另一张海报提到这适用于 TopLink 和 EclipseLink)。

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


Java SE 中实体的自动检测并不是 JPA 的一部分。依赖于此的应用程序是不可移植的。
S
Spencer Loveridge

不确定您是否正在做类似于我正在做的事情,但我使用 Maven 在单独的组件中使用 JAXB 从 XSD 生成源 java 负载。可以说这个工件被称为“基础模型”

我想导入这个包含 java 源代码的工件并在我的“基本模型”工件 jar 中的所有类上运行休眠,而不是明确指定每个类。我将“基本模型”添加为我的休眠组件的依赖项,但问题是persistence.xml 中的标签只允许您指定绝对路径。

我解决它的方法是将我的“基本模型”jar 依赖项明确地复制到我的目标目录并删除它的版本。因此,如果我构建我的“base-model”工件,它会生成“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>

然后我在下一阶段“进程类”中调用休眠插件:

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

E
Ethan Leroy

这不是解决方案,而是对使用 Spring 的人的提示:

我尝试将 org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean 与设置 persistenceXmlLocation 一起使用,但我必须提供 <class> 元素(即使 persistenceXmlLocation 只是指向 META-INF/persistence.xml)。

使用 persistenceXmlLocation 时,我可以省略这些 <class> 元素。


我在我的 LocalContainerEntityManagerFactoryBean 设置中使用了 persistenceXmlLocation 属性。但即使我省略了 <class> 元素,所有查询都可以正常工作。它在 Spring/Hibernate/Maven 应用程序上。但是在您的提示中,您会说 “当不使用 persistenceXmlLocation 时,我可以省略这些 <class> 元素。” 但对我来说恰恰相反。
@Ethan你是对的,因为 persistenceXmlLocation 覆盖 packagesToScan - 如果你查看源代码。所以在使用 packagesToScan 时不要使用它。
J
Jin Kwon

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

依赖树

我的实体.jar

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

我的服务.jar

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

我的资源.jar

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

问题

我们如何将 my-resources 中的 元素指定为临时依赖项的版本后缀工件名称?

我们如何同步 元素的值和实际的瞬态依赖项的值?

解决方案

直接(冗余?)依赖和资源过滤

我在 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>

G
Gandhi

不一定在所有情况下。

我正在使用 Jboss 7.0.8 和 Eclipselink 2.7.0。在我加载实体而不在 persistence.xml 中添加实体的情况下,我在 Jboss Standalone XML 中添加了以下系统属性:

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


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅