没有EntityManager的持久性提供程序名为persistence.xml

时间:2014-10-14 17:19:20

标签: java eclipse hibernate jpa hyperjaxb

这不是重复,因为上面的标记声称。这个问题尚未得到解答。

我正在尝试设置this tutorial以使hyperjaxb在eclipse项目中工作。如何才能看到持久性提供程序? hbm2ddl尚未在数据库中创建表结构。这就是应用程序没有看到持久性提供商的原因吗?或者是因为我的persistence.xml试图调用它的target/generated-sources目录无法访问src/main/javaTestFunctions.java的内容?以下是具体内容......这行代码:

entityManagerFactory = Persistence.createEntityManagerFactory("persistence.xml", persistenceProperties);  

抛出此错误:

Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named persistence.xml
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
    at maintest.TestFunctions.setUpPersistence(TestFunctions.java:119)
    at maintest.Main.main(Main.java:10)

抛出错误的代码在这个方法中:

public void setUpPersistence(){
    final Properties persistenceProperties = new Properties();
    InputStream is = null;
    try {
        Class<? extends TestFunctions> c = getClass();
        ClassLoader cl = c.getClassLoader();
        is = cl.getResourceAsStream("persistence.properties");
        persistenceProperties.load(is);
    }catch (IOException i) {i.printStackTrace();}
    finally {if (is != null) {try {is.close();} catch (IOException ignored) {}}}
    entityManagerFactory = Persistence.createEntityManagerFactory("persistence.xml", persistenceProperties);
}  

persistence.xml

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:orm="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <persistence-unit name="org.jvnet.hyperjaxb3.ejb.tests.po">
            <class>org.jvnet.hyperjaxb3.ejb.tests.po.Items</class>
            <class>org.jvnet.hyperjaxb3.ejb.tests.po.Items$Item</class>
            <class>org.jvnet.hyperjaxb3.ejb.tests.po.PurchaseOrderType</class>
            <class>org.jvnet.hyperjaxb3.ejb.tests.po.USAddress</class>
        </persistence-unit>
    </persistence>

persistence.properties是:

hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.username=someusername
hibernate.connection.password=somepassword
hibernate.connection.url=jdbc:mysql://localhost/somedatabasename
hibernate.hbm2ddl.auto=create-drop
hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider
hibernate.jdbc.batch_size=0

eclipse项目的目录结构是:


**编辑:**

仅仅为了踢,我将META-INF文件夹移动到与调用类相同的级别,但是我得到了同样的错误。下面是两个新的屏幕截图,显示了仍然抛出错误的persistence.xml的位置:

<小时/>

第二次编辑:

我在Class c = Class.forName("org.eclipse.persistence.jpa.PersistenceProvider");的第116行添加了TestFunctions.java,当我右键点击Main.java并执行Run As..Java Application时,会触发以下错误:

Exception in thread "main" java.lang.ClassNotFoundException: org.eclipse.persistence.jpa.PersistenceProvider
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)
    at maintest.TestFunctions.setUpPersistence(TestFunctions.java:116)
    at maintest.Main.main(Main.java:10)  

以下是新的TestFunctions.setUpPersistence()方法:

public void setUpPersistence() throws ClassNotFoundException{
    final Properties persistenceProperties = new Properties();
    InputStream is = null;
    try {
        Class<? extends TestFunctions> c = getClass();
        ClassLoader cl = c.getClassLoader();
        is = cl.getResourceAsStream("persistence.properties");
        persistenceProperties.load(is);
    }catch (IOException i) {i.printStackTrace();}
    finally {if (is != null) {try {is.close();} catch (IOException ignored) {}}}//org.jvnet.hyperjaxb3.ejb.tests.po
    Class c = Class.forName("org.eclipse.persistence.jpa.PersistenceProvider");
    entityManagerFactory = Persistence.createEntityManagerFactory(/*"org.jvnet.hyperjaxb3.ejb.tests.po"*//*"persistence.xml"*/"org.jvnet.hyperjaxb3.ejb.tests.po", persistenceProperties);
}

当我用Class c = Class.forName("org.eclipse.persistence.jpa.PersistenceProvider");替换Class c = Class.forName("org.hibernate.ejb.HibernatePersistence");时,我收到了类似的错误。但是,Class c = Class.forName("javax.persistence.spi.PersistenceProvider");不会抛出任何错误,因此程序会一直持续到相同的javax.persistence.PersistenceException: No Persistence provider for EntityManager named org.jvnet.hyperjaxb3.ejb.tests.po错误被进一步向下游抛出。

这是否告诉我们有关错误原因的更多信息?此外,hyperjaxb会创建persistence.xml并将其放在目标文件夹中。 persistence.xml位于该位置时发生此错误,并且在我移动persistence.xml时保持不变,如上所示。 hyperjaxb是不是因为与eclipse没有很好地合作而导致这个问题?

2 个答案:

答案 0 :(得分:3)

我无法抗拒,这是我最后的尝试。 :)我正在为您和任何可能遇到类似问题的用户撰写此文章。

我相信您只是在Eclipse项目配置中遇到问题。 Eclipse项目中的路径似乎不正确。

通常,当您使用File > Import... > Existing Maven Projects将现有Maven项目导入Eclipse时,m2eclipse应分析Maven项目的结构并使用(.classpath和{{1}创建Eclipse项目}文件)自动。

这些项目中的路径来自您的Eclipse .project。所以你实际上不应该创建/修改/添加/删除/复制/移动/任何Eclipse源文件夹。如果你这样做,你的Eclipse项目将不再与你的Maven项目同步,你将得到非常奇怪的结果。

有时pom.xml无法正常工作。有时你不会得到正确的源文件夹,事情会丢失等等。根据我的经验,这在一段时间内变得非常好,现在m2eclipse就像一个魅力。从我在你的斗争中看到的,可能是你有m2eclipse的旧版本。也许没有,但无论如何我建议检查它。

接下来,有时候m2eclipse仍会被钳制。在这种情况下,强烈建议您执行以下操作:

  • 清理项目:m2eclispe
  • 更新Maven项目(Alt + F5)。确保从Project > Clean...
  • 更新项目配置

enter image description here

最后,你应该得到以下项目结构:

enter image description here

具体来说,您应该获得以下源文件夹:

  • pom.xml - 主Java文件的源文件夹
  • src\main\java - 资源的源文件夹
  • src\main\resources - 生成代码的源文件夹。
    • 重要提示:不是target\generated-sources\xjc,而是target\generated-sources
    • 此文件夹包含生成的Java类。 (Hyperjaxb为他们添加了JPA注释)。
    • 它还包含target\generated-sources\xjc,它是一个持久性单元描述符。 META-INF\persistence.xml资源由JPA规范指定。这是加载持久性单元的地方。
    • 如果您已经生成了往返测试(xml-to-the-db-and-back),那么您还会在某处看到META-INF\persistence.xml类。这是一个JUnit测试类,应该可以直接执行它。 (RoundtripTest
  • Run As > JUnit Test - 测试课程。
  • src\test\java - 测试资源

这是Maven项目的标准目录布局。唯一的特性是src\test\resources源文件夹,它保存了模式编译器生成的代码。即使这是绝对标准的,Maven代码生成插件通常会在target\generated-sources\xjc目录中生成代码。

下面我发布了项目中的target\generated-sources\some-tool文件:

.classpath

重要

如果您没有此目录结构(并且您的屏幕截图显示您没有)请勿继续前进。它会失败(它适合你)。首先修复您的项目结构。不要继续前进,不要试图运行任何东西,你会遇到各种奇怪的事情,比如没有找到资源等等(你这样做)。

<?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" output="target/classes" path="src/main/java"> <attributes> <attribute name="optional" value="true"/> <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> <classpathentry including="**/*.java" kind="src" output="target/classes" path="target/generated-sources/xjc"> <attributes> <attribute name="optional" value="true"/> <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"> <attributes> <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> <classpathentry kind="src" output="target/test-classes" path="src/test/java"> <attributes> <attribute name="optional" value="true"/> <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"> <attributes> <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"> <attributes> <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> <attributes> <attribute name="maven.pomderived" value="true"/> </attributes> </classpathentry> <classpathentry kind="output" path="target/classes"/> </classpath> 重新生成项目结构并在Eclipse中清理项目。打开您的pom.xml文件,并将其与我发布的内容进行逐行比较。但请先修复项目结构。

接下来,重要的是要了解您不应该移动或拖放生成的代码。这不是正确的做法。不要这样做。 请不要继续,直到您接受此为止。不要移动或修改生成的代码。如果这样做,您将超越此代码的责任。事物以它们的方式产生,因为它以这种方式工作。因此,如果你改变它很可能它不再工作(它不适合你)。如果您需要更改任何内容,请更改配置生成的.classpath,而不是生成的代码。

现在,让我们根据以下屏幕截图分析您当前的项目结构:

enter image description here

我可以注意到:

  • pom.xml包含src\main\javamaintest\Main。如果您正在尝试编写测试,请将测试类放入TestFunctions,而不是src\test\java
  • src\main\java包含src\main\resourcespersistence.xmlsun-jaxb.episodepersistence.properties。只有schema.xsd应该在那里。
    • schema.xsdpersistence.xml是生成的文件。而且,见上文,你不能移动它们。
    • sun-jaxb.episode定义与用于测试的数据库的连接。所以它必须在测试资源中,即persistence.properties。将其放入src\test\resources最终会将此文件添加到生成的JAR中,它就像告诉每个人用于测试的数据库的用户名和密码
  • src\main\resources - 这没关系,但您的测试类应该在这里。
  • src\test\java - src\test\resources应该在这里。
  • persistence.properties - 这是错的,这应该是target\generated-sources
    • target\generated-sources\xjc包位于org.jvnet.hyperjaxb3.ejb.test.po下。它是target\generated-sources下的生成,所以我看到的意思是你已经移动了。不要这样做,见上文。
    • target\generated-sources\xjc显示为包。在您(错误地)将xjc配置为源文件夹之后,这实际上是一个遗留物。此文件夹必须包含所有生成的源,现在它只包含target\generated-sources。这意味着您移动了生成的代码。不要这样做,请看上面的命令。

因此,上面显示的Eclipse项目配置无效。以下是我为何发生这种情况的理论。我认为你的RoundtripTest没有正确处理m2eclipse,你可能缺少文件夹等。但是我没有正确生成Eclipse项目文件pom.xml你手动添加了m2eclipse并开始移动生成的代码。这不是正确的方法。

请检查并重新检查target\generated-sources,直到它与我发布的内容相同。我已经压缩了uploaded我的示例项目,这对我来说非常有用。您可以使用.classpath解压缩并导入它(而不是Maven项目)。

最后,您必须能够执行File > Import... > Existing Projects into Eclipse作为JUnit测试。测试可能会失败,但它必须运行,你不应该得到NPE等。我手头没有MySQL数据库,所以这就是我现在得到的:

RoundtripTest

这意味着实体管理器已正确启动但无法连接到数据库。如果您已在Detected [file:/C:/Projects/workspaces/hj3/hyperjaxb3-ejb-template-basic-0.6.0/target/classes/META-INF/persistence.xml]. RoundtripTest Loading entity manager factory properties. RoundtripTest Loading entity manager factory properties from [file:/C:/Projects/workspaces/hj3/hyperjaxb3-ejb-template-basic-0.6.0/target/test-classes/persistence.properties]. RoundtripTest Could not obtain connection to query metadata org.hibernate.cfg.SettingsFactory com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception: ** BEGIN NESTED EXCEPTION ** java.net.ConnectException MESSAGE: Connection refused: connect 中正确配置了测试数据库,则应该能够连接到数据库。如果您将src\test\resources\persistence.properties文件放到po.xml,则往返测试将会:

  • 解组此文件
  • 将其保存到数据库中
  • 加载回来
  • 将其与原始结果进行比较

在开始自己的实验之前,请先进行圆形测试。请勿复制代码,不要对其进行修改,也不要尝试将其折叠到目录结构中。它必须按原样运行。不要继续前进直到它。

祝你好运。

<强>更新

您可能还遇到了未解决的依赖项问题。请确保正确解析您的依赖项。这就是我所看到的:

enter image description here

如果你没有看到这一点,那就太糟糕了。您的工作区出了问题。检查Eclipse中是否有任何错误消息。也许你有类似的东西:

src\test\samples

首先快速修复它(&#34;永久标记目标......在Eclispe build&#34中被忽略;)。不要继续前进,直到此错误消失。这是一个拦截器。

答案 1 :(得分:2)

您应该传递的参数是持久性单元。 (不是文件名。)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence version="1.0" ... >
    <persistence-unit name="generated">
        <class>generated.Items</class>
        <class>generated.Items$Item</class>
        <class>generated.PurchaseOrderType</class>
        <class>generated.USAddress</class>
    </persistence-unit>
</persistence>

因此上面的generated应为persistence.xml

entityManagerFactory = Persistence.createEntityManagerFactory("generated", persistenceProperties);

为了你的坚持,应该是:

entityManagerFactory = Persistence.createEntityManagerFactory("org.jvnet.hyperjaxb3.ejb.tests.po", persistenceProperties);