Featured image for "New way to map enums with Spring Boot 4 and Hibernate 7"

New way to map enums with Spring Boot 4 and Hibernate 7

December 4th, 2025
3 minute read
Spring Spring boot Advent of Spring Hibernate JPA Spring Data

Introduction

Spring Boot 4 has been released last month! Considering all the new features it has, I decided to write about these features throughout the month of December. It will be an advent of Spring Boot 4 related tips!

When you upgrade your Spring Boot project, you not only upgrade to a new Spring Boot version, but also upgrade a ton of libraries under the hood. One of these libraries is Hibernate, which you’re probably familiar with if you worked with JPA, including when you use the spring-boot-starter-data-jpa library.

Spring Boot 4 upgrades Hibernate to v7, and with that comes the Jakarta Persistence API v3.2 (JPA). One of the new features that JPA 3.2, and thus also Hibernate 7 brings us is the new @EnumeratedValue annotation, which provides an alternative way to map enumerations in JPA.

Basic mapping with @Enumerated

Imagine the following entity and enum:

@Entity
class Medication {
    @Id
    private UUID id;
    private String name;
    private double dose;
    private DoseType doseType;
    
    // ...
}

enum DoseType {
    MILLIGRAM,
    MILLILITER,
    TABLETS
}

If you use this entity, it wants to map the dose_type column to the ordinal value of the enumeration. This would mean that a medication with DoseType.TABLETS would end up with a dose_type of 2.

This works, but you probably want to store something more readable in your database. Until now, the most common solution was to use the @Enumerated annotation and specify an EnumType.

For example, the following mapping would be the equivalent of using no @Enumerated annotation:

@Enumerated(EnumType.ORDINAL)
private DoseType doseType;

Another possibility is to use EnumType.STRING:

@Enumerated(EnumType.STRING)
private DoseType doseType;

Once you apply this annotation, Hibernate will store the 'MILLIGRAM', 'MILLILITER' or 'TABLETS' within the dose_type column.

Advanced mapping with AttributeConverter

Now, let’s imagine that we want to have a more customized mapping of our DoseType, for example by introducing a label field:

enum DoseType {
    MILLIGRAM("mg"),
    MILLILITER("ml"),
    TABLETS("tablets");
    
    private final String label;
    
    DoseType(String label) {
        this.label = label;
    }
    
    public String getLabel() {
        return this.label;
    }
}

If we want to store this label value inside our database, the only possibility we had so far was to define a custom AttributeConverter. For example:

@Converter(autoApply = true)
class DoseTypeConverter implements AttributeConverter<DoseType, String> {
    @Override
    public String convertToDatabaseColumn(DoseType type) {
        return type.getLabel();
    }

    @Override
    public DoseType convertToEntityAttribute(String dbData) {
        return Arrays
            .stream(DoseType.values())
            .filter(doseType -> doseType.getLabel().equals(dbData))
            .findAny()
            .orElseThrow();
    }
}

This works, but it does require some boilerplate code, especially if you have multiple of these enum conversions within your code.

A new kid on the block: @EnumeratedValue

With Spring Boot 4 / Hibernate 7 / JPA 3.2 we now have a new solution to the problem; the @EnumeratedValue annotation. Simply apply this to the field that contains your mapping, and you’re ready to go! No more custom conversions needed!

enum DoseType {
    MILLIGRAM("mg"),
    MILLILITER("ml"),
    TABLETS("tablets");
    
    // Starting with Spring Boot 4, this is all you need!
    @EnumeratedValue
    private final String label;
    
    // ...
}

Conclusion

If you’re using custom conversions often with enumerations in your entities, then make sure to check out @EnumeratedValue. This will surely reduce some lines of code!

This blogpost is a part of the Advent of Spring Boot 2025 series.