我想从枚举优先级列的表中获取数据。我们使用javaee 6,GF 3.1。
我们的实体看起来像这样
@Entity
@Table(name="ITEMS")
@NamedQueries({
@NamedQuery(
name = "Item.findbyPriority",
query = "select i from Item i where ORDER BY i.priority DESC" )
})
public class Item implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Integer id;
String data inputFile;
@Enumerated(EnumType.ORDINAL)
Priority priority;
...
}
定义优先级
public enum Priority {
HIGH,
NORMAL;
}
然而 Item.findbyPriority 查询按顺序排序,并以错误的顺序返回结果。如果我将Priority class更改为
public enum Priority {
NORMAL,
HIGH;
}
一切正常。但这并不是很强大。如果我添加新的优先级使用或重新排序,该怎么办?
我试图覆盖compareTo方法,但它在Enum类中是最终的。
在这种情况下我该怎么办?如何以好的方式完成?
我知道我可以将优先级存储为数字等,但是我必须手动将实体同步到Enum,这不是超级好的。 也许@PrePersist,@ PreUpldate和@PostLoad方法是可行的方法?然后jpql查询怎么样?
感谢,
米兰
答案 0 :(得分:3)
只有这样才能影响命名查询之外的优先顺序,即选择枚举属性的类型(ORDINAL,STRING)。
即使覆盖compareTo会大声说明,它也不会改变,因为在执行查询时不会调用它。原因是JPQL查询转换为SQL查询,并且没有从SQL查询调用Java方法的概念。
同样指定回调方法也无济于事,因为它们与生成查询或影响结果列表顺序无关。
您可以做的是拥有定义列表顺序的后期处理方法,并在获得执行命名查询的结果后调用该方法。
答案 1 :(得分:0)
在 JPA 2.1
之后,您可以使用 @Convert
注释。这允许在保存到数据库之前将枚举的对象转换为适合排序视图。
public enum Priority {
NORMAL(100),
HIGH(200);
private final int sortNum;
Priority(int sortNum) {
this.sortNum = sortNum;
}
public int getSortNum() {
return this.sortNum;
}
}
@Converter(autoApply = true)
public class PriorityConverter implements AttributeConverter<Priority, Integer> {
@Override
public Integer convertToDatabaseColumn(Priority attribute) {
return attribute == null ? null : attribute.getSortNum();
}
@Override
public Priority convertToEntityAttribute(Integer dbData) {
return dbData == null
? null
: Stream.of(Priority.values())
.filter(t -> t.getSortNum() == dbData)
.findFirst()
.orElseThrow(() -> new IllegalArgumentException(
String.format("Priority with sortNum %s is not exist", dbData)));
}
}
您的枚举对象将在数据库中保存为 100
或 200
。并且您将来可以轻松添加新的 Priority 对象。