Map Enum in JPA with Fixed Values

Map enum in JPA with fixed values?

For versions earlier than JPA 2.1, JPA provides only two ways to deal with enums, by their name or by their ordinal. And the standard JPA doesn't support custom types. So:

  • If you want to do custom type conversions, you'll have to use a provider extension (with Hibernate UserType, EclipseLink Converter, etc). (the second solution). ~or~
  • You'll have to use the @PrePersist and @PostLoad trick (the first solution). ~or~
  • Annotate getter and setter taking and returning the int value ~or~
  • Use an integer attribute at the entity level and perform a translation in getters and setters.

I'll illustrate the latest option (this is a basic implementation, tweak it as required):

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {

public enum Right {
READ(100), WRITE(200), EDITOR (300);

private int value;

Right(int value) { this.value = value; }

public int getValue() { return value; }

public static Right parse(int id) {
Right right = null; // Default
for (Right item : Right.values()) {
if (item.getValue()==id) {
right = item;
break;
}
}
return right;
}

};

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "AUTHORITY_ID")
private Long id;

@Column(name = "RIGHT_ID")
private int rightId;

public Right getRight () {
return Right.parse(this.rightId);
}

public void setRight(Right right) {
this.rightId = right.getValue();
}

}

JPA map collection of Enums

using Hibernate you can do

@ElementCollection(targetElement = InterestsEnum.class)
@JoinTable(name = "tblInterests", joinColumns = @JoinColumn(name = "personID"))
@Column(name = "interest", nullable = false)
@Enumerated(EnumType.STRING)
Collection<InterestsEnum> interests;

How to map mysql enum type with hypen to JPA entity?

This sort of thing is what JPA Attribute Converters are designed to help achieve.

First you'll want to map your Java enum elements to the strings found in the database, and provide a lookup method for converting a string to an element:

public enum Rating {
G("G"), // the string arguments should exactly match what's in the database.
PG("PG"),
PG13("PG-13"),
R("R"),
NC17("NC-17");

private static final Map<String, Rating> LOOKUP = Arrays.stream(values())
.collect(Collectors.toMap(Rating::getRating, Function.identity()));

private final String rating;

Rating(final String rating) {
this.rating = rating;
}

public String getRating() {
return rating;
}

public Rating fromString(final String rating) {
// You may want to include handling for the case where the given string
// doesn't map to anything - implementation is up to you.
return LOOKUP.get(rating);
}
}

Next you're going to want a class that implements javax.persistence.AttributeConverter:

public static class RatingConverter implements AttributeConverter<Rating, String> {
@Override
public String convertToDatabaseColumn(final Rating attribute) {
return attribute.getRating();
}

@Override
public Rating convertToEntityAttribute(final String dbData) {
return Rating.fromString(dbData);
}
}

From here you need to decide whether this converter should always be applied (it sounds like it probably should be), or not.

If you want it to always be used with no further configuration from you, then annotate your converter class with @javax.persistence.Converter(autoApply = true).

If you want to choose when you use the converter, then you will need to add the annotation @javax.persistence.Convert(converter = RatingConverter.class) to the Rating attribute of each JPA entity that needs it.

Personally I usually nest the converters as a static class inside the class that they convert, but you don't have to if you'd rather keep them separate.

Mapping an enum to String in R2DBC

It will map enum to string and vice versa by default without the annotation.



Related Topics



Leave a reply



Submit