Hibernate映射枚举的属性值

时间:2017-01-13 00:59:05

标签: java hibernate enums hibernate-mapping

我正在尝试使用Hibernate执行以下操作:

  • 当对象保存到数据库时,它将保存为枚举名称属性的值。
  • 当从数据库中检索对象时,该对象从数据库中读取字符串,并通过枚举的name属性的值实例化枚举。

让我解释一下。

这是枚举:

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

这是一个使用枚举的类:

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

这是数据在数据库中的显示方式:

worker
id      first_name      last_name       position        email
0       Adam            Applegate       Unspecified     adam@company.com
1       Bob             Barrett         Specialist      bob@company.com

所以基本上,当我调用workerRepository.findById(0);时,我得到的工作对象具有以下值:

id --> 0
firstName --> Adam
lastName --> Applegate
position --> Position.UNSPECIFIED
email --> adam@company.com

现在,假设我使用以下值创建一个新的worker对象:

firstName --> Chad
lastName --> Carlton
position --> Position.NOT_SPECIFIED
email --> chad@company.com

调用workerRepository.save(newWorker);后,数据库应如下所示:

id      first_name      last_name       position        email
0       Adam            Applegate       Unspecified     adam@company.com
1       Bob             Barrett         Specialist      bob@company.com
2       Chad            Carlton         Not Specialist  chad@company.com

请注意,position列的值为Position.NOT_SPECIALIST.getName()。

有没有办法在休眠中执行此操作?

2 个答案:

答案 0 :(得分:1)

我建议避免使用AttributeConverter,然后选择简单的@Enumerated(STRING)

显然,这只适用于您可以站立大写并强调位置值的情况。

public enum Position 
{
    UNSPECIFIED,
    SPECIALIST,
    NOT_SPECIALIST;
}

@Entity(name = "worker")
public class Worker 
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String firstName;

    private String lastName;

    @NotNull
    @Enumerated(STRING)
    @Column(nullable = false)
    private Position position = Position.UNSPECIFIED;

    private String email;
}

worker
id      first_name      last_name       position        email
0       Adam            Applegate       UNSPECIFIED     adam@company.com
1       Bob             Barrett         SPECIALIST      bob@company.com

当你已经Position.getId()时,你还需要Position.ordinal(),这也不清楚:Position.from(id)相当于Position.values()[id]

最后,声明"标签"不是一个好习惯。在枚举中硬编码(通常在编译代码中):只需使用ResourceBundle,您就可以为i18n做好准备。

答案 1 :(得分:0)

正如@chrylis建议的那样,我的问题的答案是使用AttributeConverter,如下所示:

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