在hibernate标准中使用mysql“order by case”

时间:2014-06-04 08:58:54

标签: mysql hibernate hibernate-criteria

我正在使用Hibernate 4.3.1 final,Mysql 5.5,我想在一些连接的实体上使用“逐个命令”的命令逻辑。

我希望实现的纯sql表示形式如下:

select adv.id, adv.published_date 
from advert as adv 
  join account as act on act.id = adv.act_id
  join account_status as aas on aas.id = act.current_aas_id
order by case aas.status
when 'pending' THEN 1
when 'approved' THEN 1
else 2
end, adv.published_date;

这会将待处理帐户和已批准帐户的广告排在拒收帐户的广告之前。

我已经设法使用hibernate标准执行所有选择查询,但我不确定如何使用该api指定case case语句。

我找到了这篇文章:

http://blog.tremend.ro/2008/06/10/how-to-order-by-a-custom-sql-formulaexpression-when-using-hibernate-criteria-api/

但我需要按顺序引用连接的实体类,我不知道该怎么做。

非常感谢任何帮助或建议。

2 个答案:

答案 0 :(得分:6)

我想我找到了解决方案。

最后,我创建了自己的Order子类,并覆盖了公共String toSqlString(Criteria,CriteriaQuery)方法:

@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
    final String[] columns = criteriaQuery.getColumnsUsingProjection( criteria, getPropertyName() );
    final StringBuilder fragment = new StringBuilder();
    fragment.append(" case ").append(columns[0]);
    fragment.append(" when 'pending' then 1 ");
    fragment.append(" when 'approved' then 1 ");
    fragment.append(" else 2 end");
    return fragment.toString();
}

重要的调用(我在订单类的原始实现中找到)是

criteriaQuery.getColumnsUsingProjection(criteria, getPropertyName());

这让我可以使用case语句访问我想要订购的列的别名。

如果其他人正在考虑这个问题,如果您订购的是不在根对象上的属性,那么请确保在条件联接中使用别名,然后在自定义订单中正确引用这些别名实例化它时的propertyName。

答案 1 :(得分:1)

除了https://stackoverflow.com/a/24077763/258559 值得一提的是,现在你正在添加像这样的Order子类

criteria.addOrder(new CustomOrder());

而不是

criteria.addOrder(CustomOrder.desc(fieldName));

因为desc / asc是静态方法,它仍然会创建Order实例而不是CustomOrder