嘿,我正在寻找搜索文本模式的方法(在jpa中)并对结果进行排序,首先是以此字符串开头的所有结果,然后是所有其他结果。 我找到了Mysql order by using search string来获得mysql的答案
大多数答案使用union
(jpa
中不存在)并强制查询数据库或打开视图。 (从代码中排序是不那个好的解决方案,因为我们使用分页来获取部分结果,因为结果大小可能非常大)
我喜欢上述链接的一个解决方案是:
select * from employee where name like '%ani%' order by locate('ani', name) asc, name asc
source
这在我看来非常清楚,但我不知道如何将其转换为jpa。看起来Order对象无法获得定位输出
欢迎任何想法
谢谢!
阿龙
修改 谢谢你的答复。我正在与jpa critiera达成共识
Iterator<Order> sortingIter = page.getSort().iterator();
ArrayList<javax.persistence.criteria.Order> order = new ArrayList<javax.persistence.criteria.Order>();
String fieldName;
while (sortingIter.hasNext()) {
Order sort = sortingIter.next();
fieldName = sort.getProperty();
order.add(sort.getDirection() == Sort.Direction.ASC ? cb
.asc(keyword.get(fieldName)) : cb.desc(keyword
.get(fieldName)));
}
虽然上述效果很好。我无法在代码中添加以下行。好像Order
对象不喜欢它们
Expression<String> fieldValue = keyword.get(fieldName);
order.add(cb.locate(fieldValue,key));
编辑2: 试着 order.add(new javax.persistence.criteria.Order(){
@Override
public javax.persistence.criteria.Order reverse() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isAscending() {
// TODO Auto-generated method stub
return true;
}
@Override
public Expression<?> getExpression() {
// TODO Auto-generated method stub
return cb.locate(fieldValue,key);
}
});
jpa没有抱怨,但查询没有得到正确的顺序
编辑3: 发现我的错误!
我传递的关键值已经包含“%”和双方......所以找不到正常工作。
现在我在一些特殊的字符上得到一些奇怪的行为:如果 - 例如 - 我有Ghurabā
这个词,查询like %ba%
会找到它。但是,似乎locate(Ghurabā,ba)
将返回0 - 意味着pattern was not found in string
任何想法如何克服这个问题?
看起来这不仅是jpa而且是mysql的行为。
SELECT *
FROM `keywords`
WHERE name LIKE '%ba%'
ORDER BY LOCATE( 'ba', name ) , name
LIMIT 0 , 30
将返回下一个结果
Ghurabā'
Khuṭabā'
qabā\
Ribāṭ
ba'urchi (cook)
Baghdad
...
请注意,它适用于“常规英文字符”,但是喜欢和定位功能之间存在不匹配
使用Collcation
:utf8_general_ci
(与utf_unicode_ci
获得相同的结果)
答案 0 :(得分:3)
这不会引起任何抱怨。
String jpql = "select e from Employee e where e.name like '%ani%' order by locate('ani', e.name) asc, e.name asc";
TypedQuery<Employee> query2 = em.createQuery(jpql ,Employee.class);
这就是hibernate所做的翻译。
Hibernate:选择employee0_.id为id1_2_,employee0_.address_id为 address5_2_,employee0_.DEPT_ID为DEPT6_2_,employee0_.manager_id为 manager7_2_,employee0_.name为name2_2_,employee0_.salary为 salary3_2_,employee0_.startDate来自员工的startDat4_2_ employee0_其中employee0_.name喜欢'%ani%'按定位排序('ani', employee0_.name)asc,employee0_.name asc
使用一些数据作为您提及的链接。
Employee 10: name: anil, salary: 59000,
Employee 1: name: anirudha, salary: 55000,
Employee 5: name: rani,
Employee 7: name: Stephanie, salary: 54000,
{anil,anirudha,rani,...}
使用CriteriQuery解决方案的相同问题
好的,你拥有我的一些观点=)
Hibernate:选择employee0_.id为id1_2_,employee0_.address_id为address5_2_,employee0_.DEPT_ID为DEPT6_2_,employee0_.manager_id为manager7_2_,employee0_.name为name2_2_,employee0_.salary为salary3_2_,employee0_.startDate为startDat4_2_来自员工employee__ employee0_.name喜欢哪里?按定位(?,employee0_.name)asc,employee0_.name asc
排序CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
Root<Employee> root = cq.from(Employee.class);
cq.where(cb.like(root.<String>get("name"), "%ani%"));
cq.orderBy(cb.asc(cb.locate(root.<String>get("name"), "ani")), cb.asc(root.get("name")));
TypedQuery<Employee> query2 = em.createQuery(cq);
printList(query2.getResultList());
尝试以上它应该有效。
Employee 10: name: anil, salary: 59000,
Employee 1: name: anirudha, salary: 55000,
Employee 5: name: rani,
Employee 7: name: Stephanie, salary: 54000,
如果您认为 ? (问号)在查询中不正确,请检查一下。 http://webdev.apl.jhu.edu/~jcs/ejava-javaee/coursedocs/605-784-site/docs/content/html/jpa-query-criteria-function.html#jpa-query-criteria-function-string-locate