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

How to Order by using Switch Case/Function in Hibernate/Grails

我有以下 hibernate/grails 域 类,这是一个遗留数据库,我没有改造这些的选项。

class Contact {
    String firstName
    String lastName
}

class Company {
    String name
}

class Customer {
    Company company
    Contact contact
}

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

我查看了 hibernate 源代码,想看看是否有一种方法可以通过使用 switch case 来侵入支持命令,但没有成功。任何人 运行 进入类似的用例?您是如何处理这个用例或任​​何建议的?

谢谢。

尽管@droggo 在查找器中是正确的,其中查询和条件查询比 HQL 更受青睐,但对于您的情况,这些选项不可用。

如果您需要排序的属性在同一个域中 class,您可以使用 derived property。您将无法 unit 测试它,并且它依赖于数据库,但您可以使用任何 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"

应该可以了。该查询将 return ListCustomer 实例按 Company 名称或 Contact 名字和姓氏排序。

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

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)
        }
    }
}

这是我的 CustomerOrderClass,它扩展了 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);
    }
}