1. Introduction
In this tutorial, we’ll discuss mapping and persisting enums in Hibernate. An enum declaration looks like the following:
public enum FLAG { ON, OFF }
Each enum constant has an ordinal which represents the sequence in the enum declaration, where the initial constant is assigned an ordinal of 0. For example, ON has ordinal value 0, OFF as 1 and so on. You can persist enum’s value as well as ordinal value.
2. @Enumerated annotation
Using the JPA-compliant @Enumerated
annotation is the most common approach of mapping enums. Enum values are persisted using two strategies:
- ORDINAL
- STRING
2.1 @Enumerated(EnumType.ORDINAL)
If you use @Enumerated(EnumType.ORDINAL)
annotation on the enum field, JPA will use the Enum.ordinal()
value when persisting a given entity in the database. EnumType.ORDINAL
is the default strategy while persisting enum.
Following is the Entity, we’ll be using in this tutorial:
@Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "name") private String name; @Enumerated(EnumType.ORDINAL) private Flag flag; // getter, setter omitted for brevity }
Notice the use of @Enumerated(EnumType.ORDINAL)
annotation. Following is the enum FLAG
:
public enum Flag { OFF, ON }
Using ORDINAL
as the strategy, will save the following values:
- NULL For null values
- 0 For the OFF enum
- 1 For the ON enum
Lets now save the Employee
entity:
Employee employee = new Employee(); employee.setName("Dummy Name"); employee.setFlag(Flag.ON); session.save(employee);
Hibernate will generate the following SQL statements:
insert into Employee (flag, name) values (?, ?) binding parameter [1] as [INTEGER] - [1] binding parameter [2] as [VARCHAR] - [Dummy Name]
Changing the order of the enum constants or inserting a new one will break the existing data model. So if there is a possibility of change in enum,
EnumType.ORDINAL
should not be preferred.
2.2 @Enumerated(EnumType.STRING)
If you use @Enumerated(EnumType.STRING)
annotation on the enum field, JPA will use the Enum.name()
value when persisting a given entity in the database. Lets now see the use of @Enumerated(EnumType.STRING
).
@Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "name") private String name; @Enumerated(EnumType.STRING) private Flag flag; // getter, setter omitted for brevity }
public enum Flag { OFF, ON }
Using ORDINAL
as the strategy, will save the following values:
- NULL For null values
- OFF For the OFF enum
- ON For the ON enum
Let us now persist the entity like the previous example,
Employee employee = new Employee(); employee.setName("Dummy Name"); employee.setFlag(Flag.ON); session.save(employee);
Hibernate will generate the following SQL statements:
insert into Employee (flag, name) values (?, ?) binding parameter [1] as [VARCHAR] - [ON] binding parameter [2] as [VARCHAR] - [Dummy Name]
3. Using AttributeConverter
Suppose you want to save T (for True) for ON and F (for False) for OFF. You can achieve this by using AttributeConverter
.
First, we’ll modify the enum FLAG
.
public enum Flag { OFF('F'), ON('T'); private final char code; Flag(char code) { this.code = code; } public static Flag fromCode(char code) { if (code == 'T' || code == 't') { return ON; } if (code == 'F' || code == 'f') { return OFF; } throw new UnsupportedOperationException("The code " + code + " is not supported!"); } public char getCode() { return code; } }
Next, we’ll modify the entity to use the converter with the enum field.
@Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "name") private String name; @Convert(converter = FlagConverter.class) private Flag flag; }
Next, we’ll create the converter.
@Converter class FlagConverter implements AttributeConverter<Flag, Character> { public Character convertToDatabaseColumn(Flag value) { if (value == null) { return null; } return value.getCode(); } public Flag convertToEntityAttribute(Character value) { if (value == null) { return null; } return Flag.fromCode(value); } }
We’ll now save the entity like the previous example.
Employee employee = new Employee(); employee.setName("Dummy Name"); employee.setFlag(Flag.ON); session.save(employee);
Hibernate will generate the following SQL queries:
insert into Employee (flag, name) values (?, ?) AttributeConverterSqlTypeDescriptorAdapter - Converted value on binding : ON -> T binding parameter [1] as [CHAR] - [T] binding parameter [2] as [VARCHAR] - [Dummy Name]