Search code examples
javahibernateenumshibernate-mapping

Hibernate map enum by property value


I'm trying to do the following using Hibernate:

  • When an object is saved to the DB, it is saved as a the value of the enum's name property.
  • When an object is retrieved from the DB, the object reads in the string from the database, and instantiates the enum by the value of the enum's name property.

Let me expound.

This is the enum:

public enum Position {

    UNSPECIFIED(1L, "Unspecified"),
    SPECIALIST(2L, "Specialist"),
    NOT_SPECIALIST(3L, "Not Specialist");

    private Long id;
    private String name;

    Position(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public static Position from(Long id) {
        for(Position position: values()) {
            if(position.getId().equals(id))
                return position;
        }

        throw new IllegalArgumentException("Cannot get position for ID " + id);
    }

    public static Position from(String name) {
        for(Position position: values()) {
            if(position.getName().toUpperCase().equals(name.toUpperCase()))
                return position;
        }

        throw new IllegalArgumentException("No such position " + name);
    }
}

This is a class that uses the enum:

@Entity(name = "worker")
public class Worker {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String lastName;
    private Position position;
    private String email;
}

This is how the data appears in the database:

worker
id      first_name      last_name       position        email
0       Adam            Applegate       Unspecified     [email protected]
1       Bob             Barrett         Specialist      [email protected]

So basically, when the I call workerRepository.findById(0); the worker object that I get back have the following values:

id --> 0
firstName --> Adam
lastName --> Applegate
position --> Position.UNSPECIFIED
email --> [email protected]

Now, let's say I create a new worker object with the following values:

firstName --> Chad
lastName --> Carlton
position --> Position.NOT_SPECIFIED
email --> [email protected]

After calling workerRepository.save(newWorker); the database should look like this:

id      first_name      last_name       position        email
0       Adam            Applegate       Unspecified     [email protected]
1       Bob             Barrett         Specialist      [email protected]
2       Chad            Carlton         Not Specialist  [email protected]

Note that the position column has the value of Position.NOT_SPECIALIST.getName().

Is there any way to do this in hibernate?


Solution

  • As @chrylis suggested, the answer to my problem was to use an AttributeConverter, like so:

    import javax.persistence.AttributeConverter;
    import javax.persistence.Converter;
    
    @Converter(autoApply = true)
    public class PositionConverter implements AttributeConverter<Position, String> {
    
        @Override
        public String convertToDatabaseColumn(Position attribute) {
            return attribute.getName();
        }
    
        @Override
        public VolleyballPlayerPosition convertToEntityAttribute(String dbData) {
            return Position.from(dbData);
        }
    }