I'm trying to build an implementation agnostic maven module which relies on JPA2. Unfortunately, the only Maven JPA dependency is JPA1 based, and consequently, I cannot use EntityManager.detach() method as that is a JPA2 option only.
Ideally, I'd love to be able to specify my javax.persistence dependency in my Pom, and require the app/container to supply the JPA2 implementation. Unfortunately, I cannot find any such dependency.
Is my only choice at this point to declare hibernate-jpa-2.0-api 1.0.0.FINAL as a provided dependency?
The Hibernate JPA 2 classes (javax.persistence...) are here:
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
I know this is a quite old post, if you want to go agnostic from the implementation, then you should use the Java EE API dependency instead.
Just add to your POM:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>${jee.version}</version>
<scope>provided</scope>
</dependency>
Where the ${jee.version} is your desired Java EE version. I'm currently using 7.0. It has all EJB, JPA and JSF APIs dependencies.
I use the javax.persistence
artifact (and not the eclipselink
artifact) from the EclipseLink Maven repository to access the JPA 2 API classes. Snippets from POM include:
<project>
...
<dependencies>
...
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
...
<repositories>
...
<repository>
<id>EclipseLink Repo</id>
<!-- note that ampersands in this URL are escaped because this is in an
xml file - un-escape them to use in browser -->
<url>http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo</url>
</repository>
...
</repositories>
...
</project>
The javax.persistence
artifact contains all the API classes, and none of the EclipseLink classes (except for two), allowing you to specify the scope as provided; this applies even for the EclipseLink JPA provider as well (which is in the eclipselink
artifact Id).
I haven't mixed the javax.persistence
artifact with the hibernate-entitymanager
artifact, which is how I managed the dependency for another project that relies on Hibernate EntityManager instead of EclipseLink for the JPA provider. A snippet from the second project's POM is shown below:
<project>
<dependencies>
...
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.6.5.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
...
</project>
I do change the dependency scopes from provided
to test
in other projects to ensure that unit tests will have a JPA provider in the classpath. This is primarily done to mask out the side-effects of using the javaee-api
dependency, which I use in the parent POM to allow compile time references to several Java EE 6 API classes.
This are the most relevant and official API for JPA2 from EclipseLink:
<repositories>
<repository>
<url>http://download.eclipse.org/rt/eclipselink/maven.repo/</url>
<id>eclipselink</id>
<layout>default</layout>
<name>Repository for library EclipseLink (JPA 2.0)</name>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
Unlike Hibernates API this are from official specification and support better generics when it comes to use Criteria API.
For the JPA 2.2 API an "official" artifact is available from maven central, see this answer.
As of today, I think the most up to date one is:
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
This is how you can use JPA in a maven:
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.10.Final</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.spec.javax.transaction</groupId>
<artifactId>jboss-transaction-api_1.2_spec</artifactId>
</exclusion>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
<exclusion>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
I was able to solve resolve my Maven JPA2 dependency by adding a couple of dependencies to the project's pom.xml file. See below for the xml code for the dependencies.
I found the latest groupId's and artifactId's versions by drilling down the directories out on Maven Central. I just walked the directory tree until I found the metadata.xml files for the persistence.core and the persistence.jpa artifacts.
Note: The dependency on persistence.jpa is what actually brings in the javax.persistence jar.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.1.Final</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.core</artifactId>
<version>2.6.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.6.4</version>
<scope>compile</scope>
</dependency>