我有以下hibernate / grails域类,这是一个遗留数据库,我没有选择重新构建这些类。
class Contact {
String firstName
String lastName
}
class Company {
String name
}
class Customer {
Company company
Contact contact
}
客户可以是公司或联系人,所以现在我有一个用例,我需要按名称对客户进行排序。 (如果公司使用名称和联系人使用firstName + lastName)。
我已经查看了hibernate源代码,以查找是否有办法通过使用switch case来支持订单,但是没有成功。有没有遇到过类似的用例?你是如何处理这个用例或任何建议的?
感谢。
答案 0 :(得分:0)
虽然@droggo在查找程序中是正确的,但查询和条件查询优先于HQL,但对于您的情况,这些选项不可用。
如果您需要排序的属性位于同一个域类中,则可以使用derived property。您将无法单元测试它,并且它依赖于数据库,但您可以使用任何GORM查询方法。相比之下,HQL可能会很难看,但它可以做到你需要的而不用大张旗鼓。
基本上,您将使用CASE WHEN
和CONCAT
的组合按计算值排序:
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);
}
}