JPA
In this example, we are going to demonstrate that a @SequenceGenerator
definition can be shared by multiple entities. According to JPA specifications (JSR 338, 11.1.48):
The SequenceGenerator annotation defines a primary key generator that may be referenced by name when a generator
element is specified for the GeneratedValue annotation. A sequence generator may be specified on the entity class or
on the primary key field or property. The scope of the generator name is global to the persistence unit (across
all generator types).
In this example we are going to use H2 in memory database and EclipseLink as JPA
provider.
We are also going to show that this feature is not supported by Hibernate (as of the current version of 5.2.8.Final)
.
Prerequisite
Basic understanding of @SequenceGenerator.
Example
In the persistence.xml, we are going to defined two persistence-units (one for EclipseLink and other for Hibernate
provider):
src/main/resources/META-INF/persistence.xml<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="test1" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"/>
</properties>
</persistence-unit>
<persistence-unit name="test2" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"/>
</properties>
</persistence-unit>
</persistence>
In pom.xml we have included following dependencies:
<dependencies> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.193</version> </dependency>
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.8.Final</version> </dependency>
<dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.6.4</version> </dependency> </dependencies>
@Entity
@SequenceGenerator(name = "mySeqGen", sequenceName = "mySeq", initialValue = 5, allocationSize = 100)
public class MyEntity1 {
@Id
@GeneratedValue(generator = "mySeqGen")
private int myId;
}
@Entity
public class MyEntity2 {
@Id
@GeneratedValue(generator = "mySeqGen")
private int myId;
}
public class Util {
public static void runExampleFor(String persistenceUnit) throws Exception {
EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnit);
EntityManager em = emf.createEntityManager();
Util.nativeQuery(em, "SELECT * FROM INFORMATION_SCHEMA.SEQUENCES");
MyEntity1 entity1 = new MyEntity1();
MyEntity2 entity2 = new MyEntity2();
em.getTransaction().begin();
em.persist(entity1);
em.persist(entity2);
em.getTransaction().commit();
Util.nativeQuery(em, "SELECT * FROM MyEntity1");
Util.nativeQuery(em, "SELECT * FROM MyEntity2");
em.close();
emf.close();
}
public static void nativeQuery(EntityManager entityManager, String s) {
System.out.println("--------\n" + s);
Query query = entityManager.createNativeQuery(s);
List list = query.getResultList();
for (Object o : list) {
if (o instanceof Object[]) {
System.out.println(Arrays.toString((Object[]) o));
} else {
System.out.println(o);
}
}
}
}
public class SequenceGeneratorScopeEclipseLink {
public static void main(String[] args) throws Exception {
Util.runExampleFor("test2");
}
}
Output
--------
SELECT * FROM INFORMATION_SCHEMA.SEQUENCES
[TEST, PUBLIC, MYSEQ, 4, 100, false, , 32, 1, 9223372036854775807, false, 10]
--------
SELECT * FROM MyEntity1
5
--------
SELECT * FROM MyEntity2
6
Hibernate Example
public class SequenceGeneratorScopeHibernate {
public static void main(String[] args) throws Exception {
Util.runExampleFor("test1");
}
}
Output
Exception in thread "main" org.hibernate.AnnotationException: Unknown Id.generator: mySeqGen
at org.hibernate.cfg.BinderHelper.makeIdGenerator(BinderHelper.java:664)
at org.hibernate.cfg.AnnotationBinder.processId(AnnotationBinder.java:2397)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2294)
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:925)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:752)
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:249)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:222)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:265)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:858)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:885)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
at com.logicbig.example.Util.runExampleFor(Util.java:13)
at com.logicbig.example.SequenceGeneratorScopeHibernate.main(SequenceGeneratorScopeHibernate.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Example ProjectDependencies and Technologies Used: - h2 1.4.193: H2 Database Engine.
- hibernate-core 5.2.8.Final: The core O/RM functionality as provided by Hibernate.
Implements javax.persistence:javax.persistence-api version 2.1 - eclipselink 2.6.4: EclipseLink build based upon Git transaction 44060b6.
Related JPA version: org.eclipse.persistence:javax.persistence version 2.1.1 - JDK 1.8
- Maven 3.3.9
|