【问题标题】:PersistenceException: No Persistence provider for EntityManager namedPersistenceException:没有名为 EntityManager 的持久性提供程序
【发布时间】:2016-04-18 20:05:57
【问题描述】:

我已经(使用 Eclipse)编写了一个使用 JPA 的小程序。现在我想使用命令行手动编译和运行这个程序。我还将所有源文件放在一个单独的目录中(不在 Eclipse 的工作空间中)。目录如下:

directory
  |- src
  |   |- javax
  |   |   |- persistence
  |   |        |- <...>
  |   |- main
  |   |- META-INF
  |   |   |- javax
  |   |   |    |- persistence
  |   |   |- persistence.xml
  |   |
  |   |- <..>
  |- run.bat

注意:我故意有 2 个 javax 目录,其中包含所有类文件。

run.bat 包含行:

javac -cp ./src ./src/main/Main.java
java -cp ./src main.Main

据我了解,我收到错误不是因为 META-INF/persistence.xml 文件的问题(不像 stackoverflow 上的许多其他人)。我这么说是因为我在 Main 中写了以下几行:

<...>
Thread.currentThread().setContextClassLoader(new ClassLoader() {
            @Override
            public Enumeration<URL> getResources(String name) throws IOException {
                System.out.println("resource requested=" + name);
                if (name.equals("META-INF/services/javax.persistence.spi.PersistenceProvider")) {
        <--- MARK --->     return Collections.enumeration(Arrays.asList(new File("src/javax/persistence/spi/PersistenceProvider.class")
                            .toURI().toURL()));
                } else if (name.equals("META-INF/persistence.xml")) {
                    return Collections.enumeration(Arrays.asList(new File("src/META-INF/persistence.xml")
                            .toURI().toURL()));
                }
                return super.getResources(name);
            }
        });
emFactory = Persistence.createEntityManagerFactory("uzduotis");
<...>

所以当我启动 run.bat 时,程序会打印:

resource name=name=META-INF/services/javax.persistence.spi.PersistenceProvider

(它永远不会到达程序要求“META-INF/persistence.xml”资源的部分)

然后它会中断并给我一个错误:

如果我将 MARKED 语句更改为

return super.getResources("src/" + name);

然后错误只说:

我错过了什么?

Peristence.xml:

编辑: 程序非常简单:没有休眠,只有几个从 REST 服务检索一些信息并使用它的类,主要使用 javax 和 w3c 外部库。项目浏览器的照片以描述其简单性。

编辑 2. 解决方案

虽然我不完全确定原因,但我找到了一种使它起作用的方法。所以如果有人能回答为什么以下更改解决了这个问题,我很乐意将其标记为答案

我将 eclipselink 和 mysql-connector-java jar 添加到 src 目录中。 eclipselink.jar 修复了这个问题,并且需要 mysql-connector-java.jar,因为我遇到了其他错误(毕竟我正在使用数据库)。最后我从

更改了 run.bat 文件中的行
java -cp ./src main.Main

java -cp ./src;./src/eclipselink.jar;./src/mysql-connector-java.jar; main.Main

【问题讨论】:

  • 也许这个答案会有所帮助:stackoverflow.com/a/1285436/1506009
  • 该帖子的哪个部分认为可以解决我的问题?
  • 看来您没有在 persistence.xml 文件中指定持久性提供程序。所以我会尝试在链接的答案中指定它。只需尝试在&lt;persistence unit name="uzduotis"&gt; 元素中添加&lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;。请记住,您需要为 HibernatePersistence 解析依赖项。
  • 哦。我可能应该指定我的程序。将很快编辑问题信息。只是让你知道我没有使用休眠,正如我在问题上所说的那样,我不认为这个问题与 persistence.xml 文件,因为这个资源从来没有被请求过。但如果你认为不是这样,请证明我错了
  • 好的。在您编辑信息后,我会再次对此进行调查。 ;)

标签: java eclipse jpa command-line


【解决方案1】:

您的应用程序似乎是标准的 Java SE 应用程序。 JPA 不会自动工作,因为标准 Java SE 环境不包含任何 JPA 接口的实现。似乎 Eclipse 将 eclipselink 添加到封面下的类路径中,因此当您从 Eclipse 中运行它时,您的程序可以工作。但是当你从命令行运行你的程序时,你需要添加eclipselink,这是一个包含JPA接口功能的库。

您可以尝试从 eclipse 项目生成 Ant 构建文件,您会看到它是否将 eclipselink 添加到 build.xml 文件的类路径中。或者更好的是,我建议使用 Maven 构建将您的项目转换为项目 - 您将能够使用 Maven 命令构建和运行您的项目,就像 Eclipse 执行它的方式一样(因为 Eclipse 在基于 Maven 的掩护下使用 Maven项目)。

编辑-解释eclipselink在JPA中的作用

javax.persistence开头的包大多是接口、注解,其实它们的类很少。它们仅定义您的应用程序如何以标准方式与底层持久性机制进行通信。另一方面,您还需要包含带有标准 JPA 接口的实现(类)的库。 javax.persistence.Persistence 只是一个门面,它将所有艰苦的工作委托给一个实现,它可能是 Eclipselink、Hibernate 或其他东西。

javax.persistence 和 EclipseLink 的关系类似于接口和类的关系。你可以在你的代码中使用接口,但是你的应用程序只有在你提供带有真实类的接口时才能工作。

也可以直接使用 Eclipselink 并跳过整个javax.persistence 层,类似地可以直接使用真实类而不通过接口。但是你需要学习 Eclipselink 的内部 API,并且不可能为 Hibernate 等替代方案更改 Eclipselink 库。您也不能将 Eclipselink 特定 API 的知识重用于使用 Hibernate 的项目。标准 API 的可重用性是标准化javax.persistence 接口的最重要案例。

也许您想知道,持久性 API 如何知道它应该在哪里委派所需的功能。有多个钩子,它是如何找出来的。可以使用provider 元素在persistence.xml 中包含主实现类的路径。或者,如果您将 Eclipselink 包含到类路径中,它就可以正常工作,因为 Eclipselink 库在标准化路径中包含特殊的文本文件,其中包含所需的信息。这个特殊文件位于路径 META-INF/services/javax.persistence.spi.PersistenceProvider 的 Eclipselink JAR 中 - 它会响铃吗?

【讨论】:

  • 您能否详细介绍一下 eclipselink 在这种情况下究竟做了什么以及为什么 javax 没有如此需要的实现?
  • 我在答案中添加了更多解释。
  • 看看这个问题stackoverflow.com/questions/19322827/…。它包含其他技术细节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-08
  • 1970-01-01
  • 2010-11-12
相关资源
最近更新 更多