如何根据特定顺序订购休眠结果
How to order result of hibernate based on a specific order
我需要发送一个查询来检索具有如下特定字符组的值:
假设我对 'XX' 感兴趣,因此它应该搜索其值以 'XX' 开头或具有“XX”(space XX)的任何字段。例如 XXCDEF
、PD XXRF
和 CMKJIEK XX
是有效结果。
我有以下查询
return是正确的结果,但我需要对它们进行排序
在某种程度上,它首先 return 那些以 XX
开头的结果,然后是其他结果。如下:
XXABCD
XXPLER
XXRFKF
AB XXAB
CD XXCD
ZZ XXOI
POLO XX
代码
Criteria criteria = session.createCriteria(Name.class, "name")
.add(Restrictions.disjunction()
.add(Restrictions.ilike("name.fname", fname + "%"))
.add(Restrictions.ilike("name.fname", "%" + " " + fname + "%"))
)
.setProjection(Projections.property("name.fname").as("fname"));
List<String> names = (List<String>) criteria.list();
愚蠢,但它可能适合你的情况。
既然你得到了正确的结果,你可以按如下方式重建你的结果:
- 选取以 XX 开头的所有结果,将它们放入列表 L1 中并进行正常排序,如 Collections.sort(L1);
- 对于所有其他结果,像 Collections.sort(L2) 作为 L2
的列表一样进行操作
最后,把它们放在一起
列表 newList = new ArrayList(L1);
newList.addAll(L2);
请注意。 Collections.sort 遵循其元素的自然顺序。
Hibernate 支持顺序:http://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch11.html#ql-ordering
由于特殊标准,我认为您必须在 Hibernate 中自定义订单。这 link 可能会有所帮助:
http://blog.tremend.ro/2008/06/10/how-to-order-by-a-custom-sql-formulaexpression-when-using-hibernate-criteria-api/
使用 JPQL (HQL):
select fname from Name
where upper(fname) like :fnameStart or upper(fname) like :fnameMiddle
order by (case when upper(fname) like :fnameStart then 1 else 2 end), fname
query.setParameter("fnameStart", "XX%");
query.setParameter("fnameMiddle", "% XX%");
有条件
使用 Criteria
就更棘手了。首先,您必须在 order
子句中求助于原生 SQL。其次,你必须绑定变量。
public class FirstNameOrder extends Order {
public FirstNameOrder() {
super("", true);
}
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return "case when upper(FIRST_NAME) like ? then 1 else 2 end";
}
}
case 表达式语法和 upper
函数名称应根据您的数据库进行更改(当然,如果不同,还应更改列名称)。
在Criteria
中添加这个很容易,但是没有API绑定参数
我试图通过将未使用的变量传递给自定义 sql 限制来欺骗 Hibernate,以便它有效地用于 order by
子句中的变量:
Criteria criteria = session.createCriteria(Name.class, "name")
.add(Restrictions.disjunction()
.add(Restrictions.ilike("name.fname", fname + "%"))
.add(Restrictions.ilike("name.fname", "%" + " " + fname + "%")))
.setProjection(Projections.property("name.fname").as("fname"))
.add(Restrictions.sqlRestriction("1 = 1", fname + "%", StringType.INSTANCE))
.addOrder(new FirstNameOrder())
.addOrder(Order.asc("fname"));
而且效果很好。
显然,不推荐这种解决方案,我建议使用 JPQL 进行此查询。
运行 两次选择,一次过滤所有以 'XX' 开头的字符串,第二次过滤其他字符串。
您可以在条件中使用谓词...像这样:
public List<Name> findByParameter(String key, String value, String orderKey)
CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Name> criteria = builder.createQuery(this.getClazz());
Root<Name> root = criteria.from(Name.getClass());
criteria.select(root);
List<Predicate> predicates = new ArrayList<Predicate>();
predicates.add(builder.equal(root.get(key), value));
criteria.where(predicates.toArray(new Predicate[predicates.size()]));
if (orderKey!=null && !orderKey.isEmpty()) {
criteria.orderBy(builder.asc(root.get(orderKey)));
}
result = this.entityManager.createQuery(criteria).getResultList();
return result;
}
如果你不想在内存中对结果进行排序,你可以修改你的标准,我给你看SQL
select * from table where fname like 'XX%' order by fname
union all
select * from table where fname like '% XX%' order by fname
union all
select * from table where fname like '% XX' order by fname
结果将是您的顺序和字母顺序,然后应用您的过滤器。
我需要发送一个查询来检索具有如下特定字符组的值:
假设我对 'XX' 感兴趣,因此它应该搜索其值以 'XX' 开头或具有“XX”(space XX)的任何字段。例如 XXCDEF
、PD XXRF
和 CMKJIEK XX
是有效结果。
我有以下查询
return是正确的结果,但我需要对它们进行排序
在某种程度上,它首先 return 那些以 XX
开头的结果,然后是其他结果。如下:
XXABCD
XXPLER
XXRFKF
AB XXAB
CD XXCD
ZZ XXOI
POLO XX
代码
Criteria criteria = session.createCriteria(Name.class, "name")
.add(Restrictions.disjunction()
.add(Restrictions.ilike("name.fname", fname + "%"))
.add(Restrictions.ilike("name.fname", "%" + " " + fname + "%"))
)
.setProjection(Projections.property("name.fname").as("fname"));
List<String> names = (List<String>) criteria.list();
愚蠢,但它可能适合你的情况。
既然你得到了正确的结果,你可以按如下方式重建你的结果:
- 选取以 XX 开头的所有结果,将它们放入列表 L1 中并进行正常排序,如 Collections.sort(L1);
- 对于所有其他结果,像 Collections.sort(L2) 作为 L2 的列表一样进行操作
最后,把它们放在一起
列表 newList = new ArrayList(L1);
newList.addAll(L2);
请注意。 Collections.sort 遵循其元素的自然顺序。
Hibernate 支持顺序:http://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch11.html#ql-ordering 由于特殊标准,我认为您必须在 Hibernate 中自定义订单。这 link 可能会有所帮助: http://blog.tremend.ro/2008/06/10/how-to-order-by-a-custom-sql-formulaexpression-when-using-hibernate-criteria-api/
使用 JPQL (HQL):
select fname from Name
where upper(fname) like :fnameStart or upper(fname) like :fnameMiddle
order by (case when upper(fname) like :fnameStart then 1 else 2 end), fname
query.setParameter("fnameStart", "XX%");
query.setParameter("fnameMiddle", "% XX%");
有条件
使用 Criteria
就更棘手了。首先,您必须在 order
子句中求助于原生 SQL。其次,你必须绑定变量。
public class FirstNameOrder extends Order {
public FirstNameOrder() {
super("", true);
}
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return "case when upper(FIRST_NAME) like ? then 1 else 2 end";
}
}
case 表达式语法和 upper
函数名称应根据您的数据库进行更改(当然,如果不同,还应更改列名称)。
在Criteria
中添加这个很容易,但是没有API绑定参数
我试图通过将未使用的变量传递给自定义 sql 限制来欺骗 Hibernate,以便它有效地用于 order by
子句中的变量:
Criteria criteria = session.createCriteria(Name.class, "name")
.add(Restrictions.disjunction()
.add(Restrictions.ilike("name.fname", fname + "%"))
.add(Restrictions.ilike("name.fname", "%" + " " + fname + "%")))
.setProjection(Projections.property("name.fname").as("fname"))
.add(Restrictions.sqlRestriction("1 = 1", fname + "%", StringType.INSTANCE))
.addOrder(new FirstNameOrder())
.addOrder(Order.asc("fname"));
而且效果很好。
显然,不推荐这种解决方案,我建议使用 JPQL 进行此查询。
运行 两次选择,一次过滤所有以 'XX' 开头的字符串,第二次过滤其他字符串。
您可以在条件中使用谓词...像这样:
public List<Name> findByParameter(String key, String value, String orderKey)
CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Name> criteria = builder.createQuery(this.getClazz());
Root<Name> root = criteria.from(Name.getClass());
criteria.select(root);
List<Predicate> predicates = new ArrayList<Predicate>();
predicates.add(builder.equal(root.get(key), value));
criteria.where(predicates.toArray(new Predicate[predicates.size()]));
if (orderKey!=null && !orderKey.isEmpty()) {
criteria.orderBy(builder.asc(root.get(orderKey)));
}
result = this.entityManager.createQuery(criteria).getResultList();
return result;
}
如果你不想在内存中对结果进行排序,你可以修改你的标准,我给你看SQL
select * from table where fname like 'XX%' order by fname
union all
select * from table where fname like '% XX%' order by fname
union all
select * from table where fname like '% XX' order by fname
结果将是您的顺序和字母顺序,然后应用您的过滤器。