Home/Learn/Hibernate & JPA/Custom AttributeConverter

Custom AttributeConverter

Advanced
Advanced

AttributeConverter<X,Y> maps between a Java type and a DB column type; use for enums, JSON objects, encrypted values, or custom domain types not natively supported by JPA.

Overview

AttributeConverter<X, Y> is a JPA interface for writing custom type mappings. X is the Java type; Y is the DB column type. Implement convertToDatabaseColumn(X) and convertToEntityAttribute(Y). Annotate with @Converter; add autoApply=true to apply it to all attributes of type X without needing @Convert on every field. Common uses: storing Java enums by a code rather than name, serialising a POJO to JSON, encrypting sensitive fields, mapping custom domain types (Money, Period, PhoneNumber) to a string or numeric column.

Enum Converter — Store by Code Not Name

Storing enums by @Enumerated(STRING) breaks if the enum is renamed. A converter stores a stable code instead, decoupling the enum identifier from DB values.

Java — enum AttributeConverter with stable code
public enum OrderStatus {
    PENDING("P"), PLACED("PL"), SHIPPED("SH"), DELIVERED("DE"), CANCELLED("CA");

    private final String code;
    OrderStatus(String code) { this.code = code; }
    public String getCode() { return code; }

    public static OrderStatus fromCode(String code) {
        return Arrays.stream(values())
            .filter(s -> s.code.equals(code))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("Unknown code: " + code));
    }
}

@Converter(autoApply = true)  // auto-applies to all OrderStatus fields in all entities
public class OrderStatusConverter implements AttributeConverter<OrderStatus, String> {

    @Override
    public String convertToDatabaseColumn(OrderStatus status) {
        return status == null ? null : status.getCode();
    }

    @Override
    public OrderStatus convertToEntityAttribute(String code) {
        return code == null ? null : OrderStatus.fromCode(code);
    }
}

JSON Converter — Store a POJO as JSON

Map a complex Java object to a single TEXT/JSON column. Useful for schemaless attributes or configurations stored inline with an entity.

Java — JSON AttributeConverter for POJO-to-TEXT column
@Converter
public class OrderMetadataConverter implements AttributeConverter<OrderMetadata, String> {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Override
    public String convertToDatabaseColumn(OrderMetadata metadata) {
        if (metadata == null) return null;
        try {
            return MAPPER.writeValueAsString(metadata);
        } catch (JsonProcessingException e) {
            throw new IllegalArgumentException("Cannot serialise OrderMetadata", e);
        }
    }

    @Override
    public OrderMetadata convertToEntityAttribute(String json) {
        if (json == null) return null;
        try {
            return MAPPER.readValue(json, OrderMetadata.class);
        } catch (JsonProcessingException e) {
            throw new IllegalArgumentException("Cannot deserialise OrderMetadata", e);
        }
    }
}

@Entity
public class Order {
    @Convert(converter = OrderMetadataConverter.class)
    @Column(columnDefinition = "TEXT")
    private OrderMetadata metadata;
}

Encrypted Field Converter

Converters are ideal for transparent field encryption: the Java code works with plaintext; the DB stores ciphertext. Inject a key management service via the Spring context.

Java — encrypted field with AttributeConverter
@Component
@Converter
public class EncryptedStringConverter implements AttributeConverter<String, String> {

    @Autowired
    private EncryptionService encryptionService;

    @Override
    public String convertToDatabaseColumn(String plaintext) {
        return plaintext == null ? null : encryptionService.encrypt(plaintext);
    }

    @Override
    public String convertToEntityAttribute(String ciphertext) {
        return ciphertext == null ? null : encryptionService.decrypt(ciphertext);
    }
}

@Entity
public class PaymentMethod {
    @Convert(converter = EncryptedStringConverter.class)
    private String cardToken;   // stored as ciphertext; loaded as plaintext
}

Key Points to Remember

  • 1AttributeConverter<X,Y>: X = Java type, Y = DB column type (usually String or primitives)
  • 2autoApply=true applies the converter globally to all fields of that type — no @Convert needed
  • 3Converters run on every read/write — keep them stateless and fast (avoid heavy I/O)
  • 4Storing enums by code (not name) decouples code from DB; rename the enum freely without migration
  • 5@Convert(converter=…) on a field overrides or disables autoApply for that specific field
  • 6Spring-managed @Component converters can use @Autowired to inject services

Interview Questions

Sign in to ask Aria
1

What are the two methods you must implement in AttributeConverter?

EasyTCS
2

Why is storing enums via an AttributeConverter safer than @Enumerated(STRING)?

MediumAmazon
3

What does autoApply=true do in @Converter?

EasyInfosys
4

How would you implement transparent field encryption using a JPA AttributeConverter?

HardPayPal
5

Can a @Converter class be a Spring @Component? What advantage does that provide?

HardOracle

Ask Aria about Custom AttributeConverter

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…