order-by-using-search-string - JPA

时间:2014-02-11 07:29:45

标签: jpa jpa-2.0 spring-data-jpa

嘿,我正在寻找搜索文本模式的方法(在jpa中)并对结果进行排序,首先是以此字符串开头的所有结果,然后是所有其他结果。 我找到了Mysql order by using search string来获得mysql的答案

大多数答案使用unionjpa中不存在)并强制查询数据库或打开视图。 (从代码中排序是那个好的解决方案,因为我们使用分页来获取部分结果,因为结果大小可能非常大)

我喜欢上述链接的一个解决方案是: 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
...

请注意,它适用于“常规英文字符”,但是喜欢和定位功能之间存在不匹配

使用Collcationutf8_general_ci(与utf_unicode_ci获得相同的结果)

1 个答案:

答案 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