hibernate - 多个参数同时搜索 Criteria Api
问题描述
我有这段代码,它只适用于输入输入字符串的一个单词。但我想进行组合搜索。例如,我想写family和name,我想和同时拥有这个名字和family的人有结果。
@Override
public List<Teacher> searchByString(String str) {
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Teacher> criteriaQuery = criteriaBuilder.createQuery(Teacher.class);
Root<Teacher> TeacherRoot = criteriaQuery.from(Teacher.class);
Predicate predicateForName
= criteriaBuilder.like(criteriaBuilder.lower(TeacherRoot.get("name")), "%" + str.toLowerCase() + "%");
Predicate predicateForFam
= criteriaBuilder.like(criteriaBuilder.lower(TeacherRoot.get("fam")), "%" + str.toLowerCase() + "%");
Predicate predicateForOtch
= criteriaBuilder.like(criteriaBuilder.lower(TeacherRoot.get("otch")), "%" + str.toLowerCase() + "%");
Predicate predicateForPhone
= criteriaBuilder.like(TeacherRoot.get("phoneNumber"), "%" + str + "%");
Predicate predicateForDate
= criteriaBuilder.like(TeacherRoot.get("dateOfBirth").as(String.class), "%" + str + "%");
Predicate predicateFinal = criteriaBuilder.or(
predicateForName,
predicateForFam,
predicateForOtch,
predicateForPhone,
predicateForDate);
criteriaQuery.where(predicateFinal);
return em.createQuery(criteriaQuery).getResultList();
}
样本数据:
1 John Newman London 8-999990999
2 John Malkovich Paris 8-999995999
3 John NewMan Moscow 8-999995999
输入字符串:约翰纽曼
结果记录:
1 John Newman London 8-999990999
3 John NewMan Moscow 8-999995999
输入字符串:John 5(姓名为 John 且电话号码为 5 的记录)
结果记录:
2 John Malkovich Paris 8-999995999
3 John NewMan Moscow 8-999995999
查询的组合可以不同。
解决方案
输入字符串 = John 5(姓名为 John 且电话号码为 5 的记录)
这里使用您输入的谓词如下所示:
Predicate predicateForName = criteriaBuilder.like(
criteriaBuilder.lower(TeacherRoot.get("name")),
"%john 5%");
//other predicates
Predicate predicateForPhone = criteriaBuilder.like(
TeacherRoot.get("phoneNumber"),
"%John 5%");
您尝试在name like "%john 5%"
和中查找记录phoneNumber like "%John 5%"
。
您必须将输入字符串拆分为单词并为每个单词使用谓词。
public List<Teacher> searchByString(String str) {
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Teacher> criteriaQuery = criteriaBuilder.createQuery(Teacher.class);
Root<Teacher> TeacherRoot = criteriaQuery.from(Teacher.class);
Predicate predicateFinal = getPredicateByInput(str, criteriaBuilder);
criteriaQuery.where(predicateFinal);
return em.createQuery(criteriaQuery).getResultList();
}
public Predicate getPredicateByInput(String input, CriteriaBuilder criteriaBuilder) {
String[] words = input.split(" ");
Predicate predicate = null;
for(String word : words) {
Predicate wordPredicate = getPredicateByWord(word, criteriaBuilder);
if(predicate == null)
predicate = wordPredicate;
else
predicate = criteriaBuilder.or(predicate, wordPredicate);
}
Objects.requireNonNull(predicate, "Null predicate is not allowed. Invalid input string '" + input + "'");
return predicate;
}
private Predicate getPredicateByWord(String word, CriteriaBuilder criteriaBuilder) {
Predicate predicateForName = criteriaBuilder.like(
criteriaBuilder.lower(TeacherRoot.get("name")),
"%" + word.toLowerCase() + "%");
Predicate predicateForFam = criteriaBuilder.like(
criteriaBuilder.lower(TeacherRoot.get("fam")),
"%" + word.toLowerCase() + "%");
Predicate predicateForOtch = criteriaBuilder.like(
criteriaBuilder.lower(TeacherRoot.get("otch")),
"%" + word.toLowerCase() + "%");
Predicate predicateForPhone = criteriaBuilder.like(
TeacherRoot.get("phoneNumber"),
"%" + word + "%");
Predicate predicateForDate = criteriaBuilder.like(
TeacherRoot.get("dateOfBirth").as(String.class),
"%" + word + "%");
return criteriaBuilder.or(
predicateForName,
predicateForFam,
predicateForOtch,
predicateForPhone,
predicateForDate);
}
Like 子句是重量级的,所以你应该尽量避免多余的谓词
推荐阅读
- jquery - 使用 jQuery 和 LeaderLine 连接 div 元素
- excel - 在线教程之后的 VBA 中出现“如果没有结束则阻止”错误
- python - Django:将数据添加到 JWT 有效负载
- python - Python Keras模型输入与层不兼容
- c# - postgres npgsql 如何使整数数组正常工作
- apollo - Apollo Federation 上的两个微服务之间的突变
- python - 让用户猜测存储的单词(字符串)直到他们猜对的代码
- graphql - Apollo federation 可以 2 个服务为相同的方法返回不同的模型
- kubernetes - Kubernetes Podspec 仅下载容器映像,但不应安装
- spring-boot - 使用 null id 保存实体 JPA