Close

JPA - Persisting Java Enum

[Updated: Mar 30, 2017, Created: Mar 29, 2017]

The persistence of Java Enum types is supported implicitly. In following quick examples we are going to show how enums are persisted by default and how to customize the default persistence by using @Enumerated annotation.

Default persistence of an enum example

By default the ordinal of an enum is persisted in the database.

public enum MyEnum {
  ConstA, ConstB, ConstC
}
@Entity
public class MyEntity {
  @Id
  private long myId;
  private MyEnum myEnum;

  public MyEntity() {
  }

  public MyEntity(long myId, MyEnum myEnum) {
      this.myId = myId;
      this.myEnum = myEnum;
  }
    .............
}
public class ExampleDefaultEnumPersistence {

  private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("test1");

  public static void main(String[] args) {
      showGeneratedTables();
      persistEntities();
      loadEntities();
  }

  private static void showGeneratedTables() {
      EntityManager em = emf.createEntityManager();
      Util.nativeQuery(em, "SHOW TABLES");
      Util.nativeQuery(em, "SHOW COLUMNS from MyEntity");
      em.close();
  }

  private static void persistEntities() {
      MyEntity entity = new MyEntity(1, MyEnum.ConstC);
      EntityManager em = emf.createEntityManager();
      em.getTransaction().begin();
      em.persist(entity);
      em.getTransaction().commit();
      em.close();
      System.out.println("MyEntity persisted: " + entity);
  }

  private static void loadEntities() {
      EntityManager em = emf.createEntityManager();
      Util.nativeQuery(em, "select * from MyEntity");
      MyEntity myEntity = em.find(MyEntity.class, 1L);
      System.out.printf("Entity loaded by entity manager: %s%n", myEntity);
      em.close();
  }
}

Output

--------
SHOW TABLES
[MYENTITY, PUBLIC]
--------
SHOW COLUMNS from MyEntity
[MYID, BIGINT(19), NO, PRI, NULL]
[MYENUM, INTEGER(10), YES, , NULL]
MyEntity persisted: MyEntity{myId=1, myEnum=ConstC}
--------
select * from MyEntity
[1, 2]
Entity loaded by entity manager: MyEntity{myId=1, myEnum=ConstC}

@Enumerated Annotation Example

The @Enumerated annotation may be used to specify whether enum should be persisted by name or by the ordinal (the default). Following snippet show it's definition:

@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Enumerated {
   EnumType value() default ORDINAL;
}
public enum EnumType {
    ORDINAL,
    STRING
}

Following is an example

@Entity
public class MyEntity2 {
  @Id
  private long myId;

  @Enumerated(EnumType.STRING)
  private MyEnum myEnum;

  public MyEntity2() {
  }

  public MyEntity2(long myId, MyEnum myEnum) {
      this.myId = myId;
      this.myEnum = myEnum;
  }
    .............
}
public class ExampleEnumeratedAnnotation {
  private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("test2");

  public static void main(String[] args) {
      showGeneratedTables();
      persistEntities();
      loadEntities();
  }

  private static void showGeneratedTables() {
      EntityManager em = emf.createEntityManager();
      Util.nativeQuery(em, "SHOW TABLES");
      Util.nativeQuery(em, "SHOW COLUMNS from MyEntity2");
      em.close();
  }

  private static void persistEntities() {
      MyEntity2 entity = new MyEntity2(1, MyEnum.ConstC);
      EntityManager em = emf.createEntityManager();
      em.getTransaction().begin();
      em.persist(entity);
      em.getTransaction().commit();
      em.close();
      System.out.println("MyEntity2 persisted: " + entity);
  }

  private static void loadEntities() {
      EntityManager em = emf.createEntityManager();
      Util.nativeQuery(em, "select * from MyEntity2");
      MyEntity2 myEntity = em.find(MyEntity2.class, 1L);
      System.out.printf("Entity loaded by entity manager: %s%n", myEntity);
      em.close();
  }
}

Output

--------
SHOW TABLES
[MYENTITY2, PUBLIC]
--------
SHOW COLUMNS from MyEntity2
[MYID, BIGINT(19), NO, PRI, NULL]
[MYENUM, VARCHAR(2147483647), YES, , NULL]
MyEntity2 persisted: MyEntity2{myId=1, myEnum=ConstC}
--------
select * from MyEntity2
[1, ConstC]
Entity loaded by entity manager: MyEntity2{myId=1, myEnum=ConstC}

Output shows that this time the generated column for our enum is of varchar type and the enum's name is persisted instead of ordinal.

Persisting ordinal is better in performance and database space as compared to enum names. However, disadvantage of using ordinal is: the new elements must be added at the end and also the order of the enum constants cannot be changed on Java side, because the persisted ordinal will go out of sync in database. Also when using 'name', the existing enum constants cannot be renamed unless we take the trouble of updating the table data as well.

Example Project

Dependencies and Technologies Used:

  • h2 1.4.193: H2 Database Engine.
  • eclipselink 2.6.4: EclipseLink build based upon Git transaction 44060b6.
    Related JPA version: org.eclipse.persistence:javax.persistence version 2.1.1
  • javax.persistence 2.1.1: javax.persistence build based upon git transaction 40384f5.
  • JDK 1.8
  • Maven 3.3.9

Jpa Persisting Java Enum Example Select All Download
  • jpa-enum-persistence
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • MyEntity2.java
          • resources
            • META-INF

    See Also