【问题标题】:How to Order by using Switch Case/Function in Hibernate/Grails如何在 Hibernate/Grails 中使用 Switch Case/Function 进行排序
【发布时间】:2016-06-22 17:53:28
【问题描述】:

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

class Contact {
    String firstName
    String lastName
}

class Company {
    String name
}

class Customer {
    Company company
    Contact contact
}

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

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

谢谢。

【问题讨论】:

  • 你能举例说明你想执行的查询吗?

标签: java hibernate grails hql grails-orm


【解决方案1】:

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

如果您需要排序的属性在同一个域类中,您将能够使用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"

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

【讨论】:

  • 我想用标准来做。我有很多遗留代码,转换为 hql 对我来说很难
  • 这不会发生。条件查询的表达力不够强,无法实现。
  • 我想我有一个解决方案。正在处理它,完成后将在此处发布。感谢您抽出宝贵时间 Emmanuel。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-25
    • 1970-01-01
    • 2020-10-03
    • 2010-09-17
    相关资源
    最近更新 更多