在按列对desc排序时,与PostgreSQL DB一起使用的Hibernate会将空值设置为大于非空值。

SQL99标准提供了关键字“NULLS LAST”来声明应将空值设置为低于非空值。

使用Hibernate的Criteria API是否可以实现“NULLS LAST”行为?

最佳答案

鉴于HHH-465不固定,并且由于史蒂夫·埃伯 Solr (Steve Ebersole)给出的原因而不会在近期内固定,您最好的选择是全局或专门使用附加到该问题的CustomNullsFirstInterceptor来更改SQL语句。

我在下面将其发布给读者(归功于Emilio Dolce):

public class CustomNullsFirstInterceptor extends EmptyInterceptor {

    private static final long serialVersionUID = -3156853534261313031L;

    private static final String ORDER_BY_TOKEN = "order by";

    public String onPrepareStatement(String sql) {

        int orderByStart = sql.toLowerCase().indexOf(ORDER_BY_TOKEN);
        if (orderByStart == -1) {
            return super.onPrepareStatement(sql);
        }
        orderByStart += ORDER_BY_TOKEN.length() + 1;
        int orderByEnd = sql.indexOf(")", orderByStart);
        if (orderByEnd == -1) {
            orderByEnd = sql.indexOf(" UNION ", orderByStart);
            if (orderByEnd == -1) {
                orderByEnd = sql.length();
            }
        }
        String orderByContent = sql.substring(orderByStart, orderByEnd);
        String[] orderByNames = orderByContent.split("\\,");
        for (int i=0; i<orderByNames.length; i++) {
            if (orderByNames[i].trim().length() > 0) {
                if (orderByNames[i].trim().toLowerCase().endsWith("desc")) {
                    orderByNames[i] += " NULLS LAST";
                } else {
                    orderByNames[i] += " NULLS FIRST";
                }
            }
        }
        orderByContent = StringUtils.join(orderByNames, ",");
        sql = sql.substring(0, orderByStart) + orderByContent + sql.substring(orderByEnd);
        return super.onPrepareStatement(sql);
    }

}

08-18 09:08