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
viapackage-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)