Close

JPA - @SequenceGenerator global scope example

[Updated: Feb 6, 2019, Created: Mar 21, 2017]

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 Project

Dependencies 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

jpa-seq-gen-scope Select All Download
  • jpa-seq-gen-scope
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • MyEntity1.java
          • resources
            • META-INF

    See Also