Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum type fields in JPA Entity

Is it possible to use Enums as a type of a field (column) in custom JPA entities? Here is an example:

@Getter @Setter
@Entity
@Table(name = "payments")
public class PaymentEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "status")
    private Integer statusId;

    public PaymentStatuses getStatus() {
        return PaymentStatuses.valueOf(statusId);
    }

    public PaymentEntity setStatus(PaymentStatuses status) {
        statusId = status == null ? null : status.getId();
        return this;
    }
}

public enum PaymentStatuses {
    CREATED(1),
    COMPLETED(2),
    CANCELED(3);


    private Integer id;

    private PaymentStatuses(Integer id) {
        this.id = id;
    }

    public Integer getId() {
         return id;
    }

    public static PaymentStatuses valueOf(Integer id) {
        for (PaymentStatuses value : values())
            if (value.getId().equals(id))
                return value;
        return null;
    }
}

Code above works fine, but approach with statusId and getStatus setStatus looks ugly a little bit.

I wanna use PaymentStatuses as a type of the field in my entity. Like this:

@Getter @Setter
@Entity
@Table(name = "payments")
public class PaymentEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "status")
    private PaymentStatuses status;
}

Tell me please, is it possible?

like image 566
Bohdan Petrenko Avatar asked Feb 15 '26 23:02

Bohdan Petrenko


2 Answers

Using @Enumerated(EnumType.ORDINAL) will not work because the ORDINAL mode starts to 0.
So the 3 first values of the enum will be represented in DB with the 0, 1 and 2 values.
while the id field in the enum to represent it in the DB goes from 1 to 3 :

CREATED(1),
COMPLETED(2),
CANCELED(3);

Besides, this way would correlate the order of elements defined in the enum with the way to represent them in database. Which not a good thing as enum values could be added/removed in the future.

A better way to address your issue is defining a javax.persistence.AttributeConverter and using it with @Convert.
So create a AttributeConverter implementation to indicate how to convert from the DB to the enum and the enum to the DB.
Then declare a PaymentStatuses status in your entity and annotate it with @Convert by specifying the AttributeConverter implementation class.

@Getter @Setter
@Entity
@Table(name = "payments")
public class PaymentEntity {
  ...
  @Convert(converter = PaymentStatusesConverter.class)
  private PaymentStatuses status;
  ...    
}

public class PaymentStatusesConverter  implements AttributeConverter<PaymentStatuses, Integer> {

    @Override
    public Integer convertToDatabaseColumn(PaymentStatuses status) {
        return status.getId();
    }

    @Override
    public PaymentStatuses convertToEntityAttribute(Integer status) {
         return PaymentStatuses.valueOf(status); 
    }
}
like image 135
davidxxx Avatar answered Feb 18 '26 11:02

davidxxx


Yes, but when you save to the database it will persist the current index of the enum value (in your case 0 for CREATED, 1 for COMPLETED, etc.) which will give you trouble if you change the enum values. To avoid this you can use the @Enumerated annotation like:

@Getter @Setter
@Entity
@Table(name = "payments")
public class PaymentEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "status")
    @Enumerated(EnumType.ORDINAL) // There is also EnumType.STRING, or you can define a custom EnumType
    private PaymentStatuses status;
}
like image 23
SrThompson Avatar answered Feb 18 '26 11:02

SrThompson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!