如何在Hibernate / Grails中使用Switch Case / Function进行排序

时间:2016-03-08 16:53:02

标签: java hibernate grails hql gorm

我有以下hibernate / grails域类,这是一个遗留数据库,我没有选择重新构建这些类。

class Contact {
    String firstName
    String lastName
}

class Company {
    String name
}

class Customer {
    Company company
    Contact contact
}

客户可以是公司或联系人,所以现在我有一个用例,我需要按名称对客户进行排序。 (如果公司使用名称和联系人使用firstName + lastName)。

我已经查看了hibernate源代码,以查找是否有办法通过使用switch case来支持订单,但是没有成功。有没有遇到过类似的用例?你是如何处理这个用例或任​​何建议的?

感谢。

2 个答案:

答案 0 :(得分:0)

虽然@droggo在查找程序中是正确的,但查询和条件查询优先于HQL,但对于您的情况,这些选项不可用。

如果您需要排序的属性位于同一个域类中,则可以使用derived property。您将无法单元测试它,并且它依赖于数据库,但您可以使用任何GORM查询方法。相比之下,HQL可能会很难看,但它可以做到你需要的而不用大张旗鼓。

使用HQL完成

基本上,您将使用CASE WHENCONCAT的组合按计算值排序:

def customers = Customer.executeQuery "SELECT cust FROM Customer AS cust LEFT OUTER JOIN cust.company AS comp LEFT OUTER JOIN cust.contact AS cont ORDER BY CASE WHEN comp.id IS NULL THEN CONCAT(cont.firstName, cont.lastName) ELSE comp.name END"

应该这样做。该查询将返回List Customer个实例,这些实例按Company名称或Contact名字和姓氏排序。

答案 1 :(得分:0)

终于能够想出一个解决方案。这不是一个非常通用的解决方案,专门针对我的用例量身定制。

def instances = searchCriteria.list(criteria) {

    createAlias('customer', 'cust', CriteriaSpecification.INNER_JOIN)
    createAlias('cust.company', 'cmp', CriteriaSpecification.LEFT_JOIN)
    createAlias('cust.user', 'user', CriteriaSpecification.LEFT_JOIN)

     if(sortCol) {
        if(sortCol == 'customer') {
            order(CustomerOrder.by('cust', 'cmp', direction))
        }
        else {
            order(sortCol, direction)
        }
    }
}

这是我的CustomerOrder类,它扩展了Hibernate Order

import org.hibernate.criterion.Order;
import org.hibernate.criterion.CriteriaQuery;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;

public class CustomerOrder extends Order {

    private String companyAlias
    private String userAlias
    private boolean ascending

    protected CustomerOrder(String userAlias, String companyAlias, boolean ascending) {
        super("", true);
        this.companyAlias = companyAlias
        this.userAlias = userAlias
        this.ascending = ascending
    }

    public String toString() {
        return companyAlias  + "-" + userAlias;
    }

    public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        String[] firstName = criteriaQuery.getColumnsUsingProjection(
            criteria, "${userAlias}.firstName");
        String[] lastName = criteriaQuery.getColumnsUsingProjection(
            criteria, "${userAlias}.lastName");

        String[] companyId = criteriaQuery.getColumnsUsingProjection(
            criteria, "${companyAlias}.id");
        String[] companyName = criteriaQuery.getColumnsUsingProjection(
            criteria, "${companyAlias}.name");

        """
            CASE WHEN ${companyId[0]} IS NULL
                THEN LOWER(RTRIM(LTRIM(${lastName[0]} + ', ' + ${firstName[0]})))
                ELSE LOWER(RTRIM(LTRIM(${companyName[0]})))
            END ${ascending ? "asc" : "desc" }
        """
    }

    public static Order by(String userAlias, String companyAlias, String direction) {
        boolean ascending = (!direction || direction.equalsIgnoreCase('asc'));
        return new CustomerOrder(userAlias, companyAlias, ascending);
    }
}