Hibernate order by nulls last

Hibernate与PostgreSQL DB一起使用,当按列排序desc时,将null值设置为高于非null值。

SQL99标准提供关键字“NULLS LAST”来声明空值应该低于非空值。

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

鉴于HHH-465没有修复,并且由于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 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); } } 

如前所述,此function已在Hibernate 4.2.x和4.3.x版本中实现。

它可以用作例如:

 Criteria criteria = ...; criteria.addOrder( Order.desc( "name" ).nulls(NullPrecedence.FIRST) ); 

Hibernate v4.3 javadocs在这里不那么有用了 。

您可以在hibernate属性中配置“nulls first”/“nulls last”,这样默认情况下它将被任何条件调用拾取: hibernate.order_by.default_null_ordering=last (或=first )。

有关详细信息,请参阅此hibernate提交 。

这是我对class级的更新(Pascal Thivent):

 for (int i = 0; i < orderByNames.length; i++) { if (orderByNames[i].trim().length() > 0) { String orderName = orderByNames[i].trim().toLowerCase(); if (orderName.contains("desc")) { orderByNames[i] = orderName.replace("desc", "desc NULLS LAST"); } else { orderByNames[i] = orderName.replace("asc", "asc NULLS FIRST"); } } } 

这解决了这个问题:

如果sql在订购后有限制/偏移,那么这会打破 – Sathish 2011年4月1日14:52

这里也是你如何在JPA(hibernate)中使用它:

 Session session = entityManager.unwrap(Session.class); Session nullsSortingProperlySession = null; try { // perform a query guaranteeing that nulls will sort last nullsSortingProperlySession = session.getSessionFactory().withOptions() .interceptor(new GuaranteeNullsFirstInterceptor()) .openSession(); } finally { // release the session, or the db connections will spiral try { if (nullsSortingProperlySession != null) { nullsSortingProperlySession.close(); } } catch (Exception e) { logger.error("Error closing session", e); } } 

我已经在postgres上测试了它,它修复了我们所拥有的’nulls高于非nulls’问题。

另一种变体,如果您动态创建SQL并且不使用Criteria API:

COALESCE(,’0’)[ASC | DESC]

这适用于varchar或数字列。

似乎有一个更改请求/错误票据打开