Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 控制Hibernate EnumType.STRING属性的排序顺序_Java_Hibernate_Orm_Enums_Hql - Fatal编程技术网

Java 控制Hibernate EnumType.STRING属性的排序顺序

Java 控制Hibernate EnumType.STRING属性的排序顺序,java,hibernate,orm,enums,hql,Java,Hibernate,Orm,Enums,Hql,目前,我的项目使用的是@Enumerated(EnumType.ORDINAL),因此当我按此列排序时,它是基于枚举中的顺序排序的,这很好。但是我需要向枚举添加一些附加值,这些值需要插入枚举值列表中的不同位置,不能只是添加到底部以保持正确的排序顺序 如果我这样做的话,我的数据库就会乱七八糟。我必须编写一些脚本,将所有这些序号值转换为正确的新序号。以后可能需要添加更多的状态。因为我必须修复数据库中的所有数据,所以我只想做一次,因为这将是一项艰巨的任务 因此,我考虑切换到EnumType.STRIN

目前,我的项目使用的是
@Enumerated(EnumType.ORDINAL)
,因此当我按此列排序时,它是基于
枚举中的顺序排序的,这很好。但是我需要向
枚举添加一些附加值,这些值需要插入枚举值列表中的不同位置,不能只是添加到底部以保持正确的排序顺序

如果我这样做的话,我的数据库就会乱七八糟。我必须编写一些脚本,将所有这些序号值转换为正确的新序号。以后可能需要添加更多的状态。因为我必须修复数据库中的所有数据,所以我只想做一次,因为这将是一项艰巨的任务

因此,我考虑切换到
EnumType.STRING
,这样就不必重新映射数据库中的顺序值。但是如果我这样做了,那么我该如何正确排序呢?枚举字符串的字母顺序不是我需要的顺序

使用下面的类,当我按属性“status”排序时,结果按以下顺序显示:

hql = "from Project order by status"

Development
Planning
Production
我希望它们按此顺序出现,而不使用
EnumType.ORDINAL

Planning
Development
Production
不为
enum
创建一个表,或向
项目
类添加一个额外的列,这是可能的吗?我尝试过这个,但它引发了一个异常:

hql = "from Project order by status.sort"
枚举:

public enum Status {

    PLANNING("Planning", 0),
    DEVELOPMENT("Development", 1),
    PRODUCTION("Production", 2);

    private final String name;
    private final int sort;
    private Status(String name, int sort) {
        this.name = name;
        this.sort = sort;
    }
    @Override
    public String toString() {
        return name;
    }
}
实体:

@Entity
public class Project {
    private Long id;
    private Status status;

    @Id
    @GeneratedValue
    public Long getId() {
        return this.id;
    }
    private void setId(Long id) {
        this.id = id;
    }
    @Enumerated(EnumType.STRING)
    public Status getStatus() {
        return status;
    }
    public void setStatus(Status status) {
        this.status = status;
    }
}
@Entity
public class Project {
    private Long id;
    private int statusCode;

    @Id @GeneratedValue
    public Long getId() {
        return this.id;
    }
    private void setId(Long id) {
        this.id = id;
    }

    @Transient
    public Status getStatus () {
        return Status.parse(this.statusCode);
    }
    public void setStatus(Status status) {
        this.statusCode = status.getCode();
    }

    protected int getStatusCode() {
        return statusCode;
    }
    protected void setStatusCode(int statusCode) {
        this.statusCode = statusCode;
    }
}
因此,我考虑切换到EnumType.STRING,这样就不必再次映射数据库中的序号值。但是如果我这样做了,那么我该如何正确排序呢?枚举字符串的字母顺序不是我需要的顺序

我个人完全避免使用邪恶的
EnumType.ORDINAL
,因为仅仅改变常量的顺序就可以阻止持久性逻辑。邪恶。也就是说,
EnumType.STRING实际上并不总是合适的

在您的情况下,我将(使用标准JPA)执行以下操作:在实体级别持久化
int
,并在getter/setters中执行枚举转换。像这样的。首先,枚举:

public enum Status {
    PLANNING("Planning", 100),
    DEVELOPMENT("Development", 200),
    PRODUCTION("Production", 300);

    private final String label;
    private final int code;

    private Status(String label, int code) {
        this.label = label;
        this.code = code;
    }

    public int getCode() { return this.code; }

    private static final Map<Integer,Status> map;
    static {
        map = new HashMap<Integer,Status>();
        for (Status v : Status.values()) {
            map.put(v.code, v);
        }
    }
    public static Status parse(int i) {
        return map.get(i);
    }
}
int
表示的getter/setter受到保护。公共getter/setter处理转换

另一种解决方案是使用自定义类型(以可移植性为代价)

相关问题

@Pascal:很好,这正是我所希望的解决方案。我的问题似乎需要一点技巧,而你的“技巧”似乎尽可能优雅。我试试看。谢谢@帕斯卡:很好用!当然,我必须更改查询以引用属性
statusCode
,其值为
Status.PLANNING.getCode()
,而不是
Status
Status.PLANNING
。为什么
EnumType.ORDINAL
是邪恶的?它很小,很快。好的,您(真的)不应该更改枚举声明中的顺序,但是文件中的注释可以做到这一点
EnumType.STRING
具有相同的缺陷,您无法更改枚举的名称。这两种方法都有各自的问题。当您添加新的枚举值时,这种技术可以很好地工作,但它不允许您对现有值重新排序。它还要求重新映射数据库以使用新代码。因此,让字段保持原样,然后实现一个
比较器
类不是更好吗?@Will每次我使用
序数
时,它都会回来咬我,这是另一个例子。如果我使用了
STRING
,至少它不需要数据库更新。我发现我更可能需要在枚举中添加或删除元素,而不是重命名它们@帕斯卡的解决方案可能并不适合所有人,但它非常适合我的情况。