Prateek
4 min readJun 21, 2021

JPA — How To Map Java enum To PostgreSQL enum Type

Description: This application maps a Java enum type to PostgreSQL enum type.

Key points:

  • define a custom Hibernate EnumType
  • register this custom EnumType via package-info.java
  • annotate the corresponding entity field @Type

Author.java

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Author implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private int age;
private String name;

@Enumerated(EnumType.STRING)
@Type(type = "genre_enum_type")
@Column(columnDefinition = "genre_info")

private GenreType genre;
}

GenreType.java

public enum GenreType {
HORROR, ANTHOLOGY, HISTORY
}

AuthorRepository.java

@Repository
public interface AuthorRepository extends JpaRepository<Author, Long> {
}

BookStoreRepository.java

@Service
@RequiredArgsConstructor
public class BookstoreService {

private final AuthorRepository authorRepository;

public void persistNewAuthor() {
Author author = new Author();
author.setName("Maryus Yarn");
author.setAge(34);
author.setGenre(GenreType.HORROR);

authorRepository.save(author);
}

public void fetchAuthor() {
Author author = authorRepository.findById(1L).orElseThrow(() -> new RuntimeException(""));
System.out.println(author);
}
}

package-info.java

@org.hibernate.annotations.TypeDef(name = "genre_enum_type", typeClass = PostgreSQLEnumType.class)

package com.bookstore.type;

PostgresSQLEnumType.java

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.EnumType;

public class PostgreSQLEnumType extends EnumType {

@Override
public void nullSafeSet(PreparedStatement ps, Object obj, int index,
SharedSessionContractImplementor session) throws HibernateException, SQLException {
if (obj == null) {
ps.setNull(index, Types.OTHER);
} else {
ps.setObject(index, obj.toString(), Types.OTHER);
}
}
}

MainApplication.java

@SpringBootApplication
public class MainApplication {

private final BookstoreService bookstoreService;

public MainApplication(BookstoreService bookstoreService) {
this.bookstoreService = bookstoreService;
}

public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}

@Bean
public ApplicationRunner init() {
return args -> {
bookstoreService.persistNewAuthor();
bookstoreService.fetchAuthor();
};
}
}

application.properties

spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=postgres

spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL95Dialect

spring.datasource.initialization-mode=always
spring.datasource.platform=postgresql

spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

spring.jpa.open-in-view=false

schema-postgres.sql

DROP TYPE IF EXISTS genre_info CASCADE;
CREATE TYPE genre_info AS ENUM ('HORROR', 'ANTHOLOGY', 'HISTORY')

Hibernate: insert into author (age, genre, name) values (?, ?, ?)
Hibernate: select author0_.id as id1_0_0_, author0_.age as age2_0_0_, author0_.genre as genre3_0_0_, author0_.name as name4_0_0_ from author author0_ where author0_.id=?
Author(id=1, age=34, name=Maryus Yarn, genre=HORROR)

— — — — — — — — — — — — — — — — — — — — — — — — —

How To Map Java enum To PostgreSQL enum Type Via Hibernate Types Library

Description: This application maps a Java enum type to PostgreSQL enum type via Hibernate Types library.

Key points:

  • install Hibernate Types library via pom.xml
  • use @TypeDef to specify the needed type class
  • annotate the corresponding entity field with @Type

Code is not working — will revisit

— — — — — — — — — — — — — — -

Quickest Mapping Of Java Enums

Description: This application uses EnumType.ORDINAL and EnumType.STRING for mapping Java enum type to database. As a rule of thumb, strive to keep the data types as small as possible (e.g., for EnumType.ORDINAL use TINYINT/SMALLINT, while for EnumType.STRING use VARCHAR(max_needed_bytes)). Relying on EnumType.ORDINAL should be more efficient but is less expressive than EnumType.STRING.

Key points:

  • strive for smallest data types (e.g., for EnumType.ORDINAL set @Column(columnDefinition = "TINYINT"))

Author.java

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Author implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private int age;
private String name;

// @Enumerated(EnumType.STRING)
// @Column(length = 9)
@Enumerated(EnumType.ORDINAL)
@Column(columnDefinition = "TINYINT")

private GenreType genre;
}

GenreType.java

public enum GenreType {
HORROR, ANTHOLOGY, HISTORY
}

AuthorRepository.java

@Repository
public interface AuthorRepository extends JpaRepository<Author, Long> {
}

BookStoreService.java

@Service
@RequiredArgsConstructor
public class BookstoreService {

private final AuthorRepository authorRepository;

public void persistNewAuthor() {
Author author = new Author();
author.setName("Maryus Yarn");
author.setAge(34);
author.setGenre(GenreType.HISTORY);

authorRepository.save(author);
}

public void fetchAuthor() {
Author author = authorRepository.findById(1L).orElseThrow(() -> new RuntimeException(""));
System.out.println(author);
}
}

MainApp.java

@SpringBootApplication
public class MainApplication {

private final BookstoreService bookstoreService;

public MainApplication(BookstoreService bookstoreService) {
this.bookstoreService = bookstoreService;
}

public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}

@Bean
public ApplicationRunner init() {
return args -> {
bookstoreService.persistNewAuthor();
bookstoreService.fetchAuthor();
};
}
}

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/bookstoredb?createDatabaseIfNotExist=true
spring.datasource.username=root
spring.datasource.password=root

spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

spring.datasource.initialization-mode=always
spring.datasource.platform=mysql

spring.jpa.open-in-view=false

data-mysql.sql

-- for @Enumerated(EnumType.ORDINAL)
insert into author (age, name, genre, id) values (23, "Mark Janel", 1, 1);
insert into author (age, name, genre, id) values (43, "Olivia Goy", 0, 2);
insert into author (age, name, genre, id) values (51, "Quartis Young", 1, 3);
insert into author (age, name, genre, id) values (34, "Joana Nimar", 2, 4);
insert into author (age, name, genre, id) values (38, "Alicia Tom", 1, 5);
insert into author (age, name, genre, id) values (56, "Katy Loin", 1, 6);

-- for @Enumerated(EnumType.STRING)
--insert into author (age, name, genre, id) values (23, "Mark Janel", "ANTHOLOGY", 1);
--insert into author (age, name, genre, id) values (43, "Olivia Goy", "HORROR", 2);
--insert into author (age, name, genre, id) values (51, "Quartis Young", "ANTHOLOGY", 3);
--insert into author (age, name, genre, id) values (34, "Joana Nimar", "HISTORY", 4);
--insert into author (age, name, genre, id) values (38, "Alicia Tom", "ANTHOLOGY", 5);
--insert into author (age, name, genre, id) values (56, "Katy Loin", "ANTHOLOGY", 6);

Console Output —

Hibernate: insert into author (age, genre, name) values (?, ?, ?)
Hibernate: select author0_.id as id1_0_0_, author0_.age as age2_0_0_, author0_.genre as genre3_0_0_, author0_.name as name4_0_0_ from author author0_ where author0_.id=?
Author(id=1, age=23, name=Mark Janel, genre=ANTHOLOGY)

Prateek
Prateek

Written by Prateek

Java Developer and enthusiast

Responses (1)