Java enums map cleanly to database columns with modern Jakarta Persistence and Hibernate. The important decision is not whether Hibernate can persist an enum, but how the enum should be represented in the database.
For most applications, the safest default is explicit: annotate the enum field with @Enumerated(EnumType.STRING). That stores values such as ROCK, PAPER and SCISSORS instead of fragile numeric ordinals.
Modern Java 25 enum example
The enum itself needs no Hibernate-specific code:
package com.mcnz.rps;
public enum Gesture {
ROCK,
PAPER,
SCISSORS
}Map enums with Jakarta Persistence
Modern Hibernate uses the jakarta.persistence API. Older examples that import javax.persistence predate the Jakarta namespace migration and should be updated.
Here is a compact entity suitable for a modern Java 25 and Hibernate application:
package com.mcnz.rps;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import java.time.Instant;
@Entity
public class GameSummary {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
private Gesture clientGesture;
@Enumerated(EnumType.STRING)
private Gesture serverGesture;
private String result;
private Instant playedAt = Instant.now();
protected GameSummary() {
}
public GameSummary(
Gesture clientGesture,
Gesture serverGesture,
String result) {
this.clientGesture = clientGesture;
this.serverGesture = serverGesture;
this.result = result;
}
}This version replaces the old java.util.Date approach with java.time.Instant and uses explicit enum mappings so the database representation is obvious from the entity definition.
EnumType.STRING versus EnumType.ORDINAL
If an enum field has no @Enumerated annotation and no converter or other mapping overrides it, enum persistence can fall back to ordinal semantics. That means the position of each constant is stored as a number:
ROCKbecomes0PAPERbecomes1SCISSORSbecomes2
Ordinal persistence is compact, but it is brittle. If someone later inserts a new enum constant or reorders the existing constants, old database values can acquire a completely different meaning.
Ordinal enum mapping stores numeric positions, which can become unsafe if the enum order changes.
Prefer EnumType.STRING
For most domain enums, explicitly store the enum name:
@Enumerated(EnumType.STRING)
private Gesture clientGesture;
@Enumerated(EnumType.STRING)
private Gesture serverGesture;The database now stores ROCK, PAPER or SCISSORS. These values are readable and remain stable if the declaration order changes.
EnumType.STRING stores the Java enum constant name instead of its ordinal position.
Persist the entity with modern Hibernate
Hibernate's native Session API works well with try-with-resources. The transaction can be expressed clearly without the old EntityManagerFactory boilerplate shown in many legacy tutorials:
var game = new GameSummary(
Gesture.PAPER,
Gesture.ROCK,
"win"
);
try (var session = sessionFactory.openSession()) {
var transaction = session.beginTransaction();
try {
session.persist(game);
transaction.commit();
} catch (RuntimeException e) {
if (transaction.isActive()) {
transaction.rollback();
}
throw e;
}
}If your application standardizes on Jakarta Persistence rather than Hibernate's native API, the same entity can be persisted through an EntityManager. The enum annotations are portable Jakarta Persistence mappings and do not tie the entity to Hibernate.
What about hbm.xml enum mappings?
Hibernate still has extensive mapping capabilities, but new applications should normally prefer annotations or Jakarta Persistence XML rather than introducing legacy hbm.xml mappings for a simple enum. The old Hibernate-specific org.hibernate.type.EnumType configuration shown in historical examples is unnecessary for ordinary enum persistence.
If you are maintaining an older application that already uses hbm.xml, there may be good reasons to leave the mapping architecture in place until a planned migration. For new Java 25 code, however, this annotation is usually all that is required:
@Enumerated(EnumType.STRING)
private Gesture gesture;When the database value should differ from the enum name
EnumType.STRING stores the Java constant name. Sometimes a database schema requires a different stable value, such as R, P and S. In that situation, use a Jakarta Persistence AttributeConverter rather than relying on enum ordinals.
package com.mcnz.rps;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
@Converter
public class GestureConverter
implements AttributeConverter<Gesture, String> {
@Override
public String convertToDatabaseColumn(Gesture gesture) {
if (gesture == null) {
return null;
}
return switch (gesture) {
case ROCK -> "R";
case PAPER -> "P";
case SCISSORS -> "S";
};
}
@Override
public Gesture convertToEntityAttribute(String value) {
if (value == null) {
return null;
}
return switch (value) {
case "R" -> Gesture.ROCK;
case "P" -> Gesture.PAPER;
case "S" -> Gesture.SCISSORS;
default -> throw new IllegalArgumentException(
"Unknown gesture: " + value
);
};
}
}The Java 25 switch expression makes the conversion concise and exhaustive. If a new Gesture constant is added, the compiler helps identify code that must be updated.
Modern Hibernate enum mapping recommendations
- Use
jakarta.persistence, not the legacyjavax.persistencepackage. - Prefer
@Enumerated(EnumType.STRING)for ordinary domain enums. - Avoid
EnumType.ORDINALunless the numeric representation is deliberately part of the schema contract. - Use an
AttributeConverterwhen the database representation must differ from the Java enum constant name. - Use modern
java.timetypes instead ofjava.util.Datein new entity models. - Prefer annotations for new Hibernate applications instead of adding legacy
hbm.xmlsolely to map enums.
Modern JPA and Hibernate enum mapping is therefore straightforward. Make the database representation explicit, favor stable String values, and use a converter when your persistence model needs its own durable codes.

Cameron McKenzie is an AWS Certified AI Practitioner, Machine Learning Engineer, Solutions Architect and author of many popular books in the software development and Cloud Computing space. His growing YouTube channel training devs in Java, Spring, AI and ML has well over 30,000 subscribers.