I am developing a JavaSE application using JPA. Unfortunately, I get null
after calling:
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
Below you will find:
- A snippet of my code that invokes
EntityManagerFactory
and unexpectedly returnsnull
- My
persistence.xml
file - My project structure
Snippet of my code:
public class Main {
private static final String PERSISTENCE_UNIT_NAME = "MeineJpaPU";
private static EntityManagerFactory factory;
public static void main(String[] args) {
// I get null on this line!!!
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
// do stuff with entity manager
...
}
}
My persistence.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="MeineJpaPU" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<class>path.to.package.server.Todo</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/test"/>
<property name="javax.persistence.jdbc.user" value="postgres"/>
<property name="javax.persistence.jdbc.password" value="postgres"/>
</properties>
</persistence-unit>
</persistence>
My project structure:
You must move persistence.xml
file to an appropriate location.
More specifically, add META-INF/persistence.xml
file to the root of a source folder.
In this case, the following is an appropriate location: src\main\java\META-INF\persistence.xml
Here are the details: (taken from the JPA spec)
A persistence.xml file defines a persistence unit. The persistence.xml file is located in the META-INF directory of the root of the persistence unit.
The root of the persistence unit is the key here.
If you are a non-Java EE app
The jar file or directory whose META-INF directory contains the persistence.xml file is termed the root of the persistence unit.
If you are in a Java EE app, the following are valid
In Java EE environments, the root of a persistence unit must be one of the following:
- an EJB-JAR file
- the WEB-INF/classes directory of a WAR file[80]
- a jar file in the WEB-INF/lib directory of a WAR file
- a jar file in the EAR library directory
- an application client jar file
Quick advice:
- check if persistence.xml is in your classpath
- check if hibernate provider is in your classpath
With using JPA in standalone application (outside of JavaEE), a persistence provider needs to be specified somewhere. This can be done in two ways that I know of:
- either add provider element into the persistence unit:
<provider>org.hibernate.ejb.HibernatePersistence</provider>
(as described in correct answer by Chris here: https://stackoverflow.com/a/1285436/784594) - or provider for interface javax.persistence.spi.PersistenceProvider must be specified as a service, see here: http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html (this is usually included when you include hibernate,or another JPA implementation, into your classpath
In my case, I found out that due to maven misconfiguration, hibernate-entitymanager.jar was not included as a dependency, even if it was a transient dependency of other module.
See also answers here: No Persistence provider for EntityManager named
I recently upgraded NB 8.1 to 8.2 and suddenly faced this problem and spent 2 days breaking my head to resolve. Up to 8.1, removing processorpath (mentioned above by others) worked. With 8.2, the problem persisted.
Finally, I found that the eclipselink.jar is missing in the default library of EclipseLink (JPA 2.1). I added the file to the definition of the library and voila - it started working!
So in my case, everything was in the class path, but I had to add
Class c = Class.forName("org.eclipse.persistence.jpa.PersistenceProvider");
I think this caused the PersistenceProvider to register itself with the javax classes. I have had to do something similar for JDBC drivers in the past as well.
If you don't want to move your META-INF folder (maybe because that's where your IDE created it and you don't want to confuse it), and if you are using Maven, you can tell Maven where to look for META-INF using the <resources>
tag. See: http://maven.apache.org/plugins/maven-resources-plugin/examples/resource-directory.html
In your case:
<build>
<resources>
<resource>
<directory>src</directory>
</resource>
</resources>
</build>
Dont give JPA dependency explicity
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
Thanks,
Rahul
来源:https://stackoverflow.com/questions/19322827/no-persistence-provider-for-entitymanager-named-x