3

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?

2
  • 1
    You can use @Enumerated(EnumType.ORDINAL) Commented Feb 19, 2018 at 13:56
  • @Klaimmore ORDINAL starts to 0. It is not compatible with the id used (1, 2, 3) to represent the enum in DB. Commented Feb 19, 2018 at 14:20

3 Answers 3

8

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); 
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. All works fine. Spring data jpa find queries works fine too.
@Bohdan Petrenko Thanks for the feedback. You are welcome.
this is working fine while bringing the values from database. But while insert into database throws casting exception. Thanks in advance.
1

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;
}

Comments

0

You can use @Enumerated(EnumType.STRING) if you want your data to be stored in the db like the name of the Java enum name (CREATED, COMPLETED, CANCELED)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.