由Enum提供的JPQL订单

时间:2012-02-09 17:06:35

标签: jpa enums glassfish jpql

我想从枚举优先级列的表中获取数据。我们使用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查询怎么样?

感谢,

米兰

2 个答案:

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

您的枚举对象将在数据库中保存为 100200。并且您将来可以轻松添加新的 Priority 对象。