Enums, dates and AttributeConverter
Store enums and custom types in a form that survives the next refactor of your code.
Open this lesson in the learning hubKey points
@Enumerateddefaults toORDINAL, which stores the position. Reorder the enum and every stored row changes meaning.- Write
@Enumerated(EnumType.STRING)every time. A little wider, unambiguous, and readable in a SQL console. - For a short stable code that survives a rename, write an
AttributeConvertermapping each constant to a fixed string. @Converter(autoApply = true)applies it to every field of that type, so no entity has to mention the converter.- Hibernate 6 maps
LocalDateandInstantnatively.@Temporalis only for the old java.util.Date. - A converter runs on every read and every write of that column. Keep it pure and cheap: no lookups, no I/O, no clock.
Example
public enum OrderStatus { NEW, PAID, SHIPPED }
@Entity
public class Order {
@Enumerated(EnumType.STRING) // "PAID" - never the ordinal 1
@Column(length = 16, nullable = false)
private OrderStatus status;
private Instant placedAt; // mapped natively, no @Temporal
@Convert(converter = MoneyConverter.class)
private Money total; // stored as a bigint of cents
}
@Converter(autoApply = true)
public class MoneyConverter implements AttributeConverter<Money, Long> {
@Override
public Long convertToDatabaseColumn(Money money) {
return money == null ? null : money.cents();
}
@Override
public Money convertToEntityAttribute(Long cents) {
return cents == null ? null : Money.ofCents(cents);
}
}
ORDINAL turns a harmless enum reorder into silent data corruption.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Hibernate course, and every lesson in it is listed on the Hibernate contents page.