DetachedCriteria 排序时怎么才能支持case when
(基于hibernate3.x)
最近在做项目(Hibernate持久层)时遇到一个需求:要求根据上报时间进行排序“将未上报的数据(上报时间为Null)放到列表最前面,其余数据再按上报时间倒序排列”,无论是正序还是倒序都不能直接满足要求。这里讲一下我实现的方法,有更好的解决办法可以给我留言让我学习学习。
倒序:
正序:
自定义Order继承自org.hibernate.criterion.Order
/**
* 自定义Order排序
*/
public class CustomOrder extends Order {
private static final long serialVersionUID = 1L;
private boolean ascending;
private String propertyName;
/**
* 排序语句
*/
private String orderHql;
private boolean ignoreCase;
private NullPrecedence nullPrecedence;
public CustomOrder ignoreCase() {
ignoreCase = true;
return this;
}
public CustomOrder nulls(NullPrecedence nullPrecedence) {
this.nullPrecedence = nullPrecedence;
return this;
}
protected CustomOrder(String propertyName, boolean ascending) {
super(propertyName, ascending);
this.propertyName = propertyName;
this.ascending = ascending;
}
public static CustomOrder asc(String propertyName) {
return new CustomOrder(propertyName, true);
}
public static CustomOrder desc(String propertyName) {
return new CustomOrder(propertyName, false);
}
/**
* 通过自定义Hql语句来拓展排序功能,可以支持case when语句 <br/>
* 例句: "( CASE WHEN reporttime IS NULL THEN NOW() WHEN reporttime IS NOT NULL THEN reporttime END)"
* @param orderHql
* @return
*/
public CustomOrder orderHql(String orderHql) {
this.orderHql = orderHql;
return this;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName);
Type type = criteriaQuery.getTypeUsingProjection(criteria, propertyName);
StringBuilder fragment = new StringBuilder();
for (int i = 0; i < columns.length; i++) {
SessionFactoryImplementor factory = criteriaQuery.getFactory();
if (StringUtil.isNotEmpty(orderHql)) {
fragment.append(factory.getDialect().renderOrderByElement(orderHql.replaceAll(propertyName, columns[i]), null, ascending ? "asc" : "desc",
nullPrecedence != null ? nullPrecedence : factory.getSettings().getDefaultNullPrecedence()));
if (i < columns.length - 1) {
fragment.append(", ");
}
continue;
}
final StringBuilder expression = new StringBuilder();
boolean lower = false;
if (ignoreCase) {
int sqlType = type.sqlTypes(factory)[i];
lower = sqlType == Types.VARCHAR || sqlType == Types.CHAR || sqlType == Types.LONGVARCHAR;
}
if (lower) {
expression.append(factory.getDialect().getLowercaseFunction()).append('(');
}
expression.append(columns[i]);
if (lower)
expression.append(')');
fragment.append(factory.getDialect().renderOrderByElement(expression.toString(), null, ascending ? "asc" : "desc",
nullPrecedence != null ? nullPrecedence : factory.getSettings().getDefaultNullPrecedence()));
if (i < columns.length - 1)
fragment.append(", ");
}
return fragment.toString();
}
}
调用自定义Order
String orderHql = "( CASE WHEN reporttime IS NULL THEN NOW() WHEN reporttime IS NOT NULL THEN reporttime END)";
//detachedCriteria是DetachedCriteria的对象
detachedCriteria.addOrder(CustomOrder.desc("reporttime").orderHql(orderHql));
运行的效果:
搞定!