英文:
JPA specification has no effect with CriteriaBuilder.or() method
问题
以下是翻译好的部分:
public class VendorEmailSpecification {
public static Specification<VendorEmail> filter(String filterText) {
return new Specification<VendorEmail>() {
@Override
public Predicate toPredicate(Root<VendorEmail> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
Predicate predicate = criteriaBuilder.conjunction();
if (!StringUtils.isEmpty(filterText)) {
/***
* 这个代码块没有任何效果
**/
predicate = criteriaBuilder.or(
criteriaBuilder.like(root.get("to"), "%" + filterText + "%"),
criteriaBuilder.like(root.get("from"), "%" + filterText + "%"),
criteriaBuilder.like(root.get("subject"), "%" + filterText + "%"),
criteriaBuilder.like(root.get("message"), "%" + filterText + "%")
);
}
// 存在 ManyToOne 关联,AuthUserThread.getContext() 返回一个 User 实体对象,这部分正常工作
predicate = criteriaBuilder.and(predicate, criteriaBuilder.equal(root.get("user"), AuthUserThread.getContext()));
return predicate;
}
};
}
}
如果你需要进一步讨论或有其他问题,请随时提问。
英文:
What I want to get is like -
SELECT * FROM emials WHERE user_id = ?1 AND (`to` like '%?2%' OR `from` LIKE '%?2%' OR subject LIKE '%?2%');
To get such I have following specification like -
public class VendorEmailSpecification {
public static Specification<VendorEmail> filter(String filterText) {
return new Specification<VendorEmail>() {
@Override
public Predicate toPredicate(Root<VendorEmail> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
Predicate predicate = criteriaBuilder.conjunction();
if(!StringUtils.isEmpty(filterText)) {
/***
* this block donot have any effects
**/
predicate = criteriaBuilder.or(
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("to"),"%"+ filterText +"%")),
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("from"),"%"+ filterText +"%")),
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("subject"),"%"+ filterText +"%")),
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("message"),"%"+ filterText +"%"))
);
}
// there is an relation of ManyToOne with user and AuthUserThread.getContext() gives an object of User entity.
// this working perfectly
predicate = criteriaBuilder.and(predicate,criteriaBuilder.equal(root.get("user"), AuthUserThread.getContext()));
return predicate;
}
};
}
}
What mistake is there and how can i fix that?
答案1
得分: 1
看起来 filterText
参数在调用 toPredicate()
方法时已经超出了作用域。
如果您在 filter()
方法返回的匿名 Specification<VendorEmail>
实例中添加一个成员,并将 filterText
参数的值赋给该成员,然后更新其余代码以引用这个新成员,如下所示,应该可以解决这个问题:
public class VendorEmailSpecification {
public static Specification<VendorEmail> filter(String filterText) {
return new Specification<VendorEmail>() {
private String filterValue = filterText;
@Override
public Predicate toPredicate(Root<VendorEmail> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
Predicate predicate = criteriaBuilder.conjunction();
if (!StringUtils.isEmpty(this.filterValue)) {
/***
* this block donot have any effects
**/
predicate = criteriaBuilder.or(
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("to"), "%" + this.filterValue + "%")),
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("from"), "%" + this.filterValue + "%")),
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("subject"), "%" + this.filterValue + "%")),
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("message"), "%" + this.filterValue + "%"))
);
}
// there is a relation of ManyToOne with user and AuthUserThread.getContext() gives an object of User entity.
// this working perfectly
predicate = criteriaBuilder.and(predicate, criteriaBuilder.equal(root.get("user"), AuthUserThread.getContext()));
return predicate;
}
};
}
}
英文:
It looks like the filterText
parameter will have gone out of scope when the toPredicate()
method is called.
If you add a member to the anonymous Specification<VendorEmail>
instance returned by the filter()
method, assign the value of the filterText
parameter to the member, and update the remaining code to refer to the new member, as shown below, that should resolve the problem:
public class VendorEmailSpecification {
public static Specification<VendorEmail> filter(String filterText) {
return new Specification<VendorEmail>() {
private String filterValue = filterText;
@Override
public Predicate toPredicate(Root<VendorEmail> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
Predicate predicate = criteriaBuilder.conjunction();
if(!StringUtils.isEmpty(this.filterValue)) {
/***
* this block donot have any effects
**/
predicate = criteriaBuilder.or(
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("to"),"%"+ this.filterValue +"%")),
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("from"),"%"+ this.filterValue +"%")),
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("subject"),"%"+ this.filterValue +"%")),
criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("message"),"%"+ this.filterValue +"%"))
);
}
// there is an relation of ManyToOne with user and AuthUserThread.getContext() gives an object of User entity.
// this working perfectly
predicate = criteriaBuilder.and(predicate,criteriaBuilder.equal(root.get("user"), AuthUserThread.getContext()));
return predicate;
}
};
}
}
答案2
得分: 1
我用另一种方法解决了这个问题 -
public class VendorEmailSpecification {
public static Specification<VendorEmail> filter(String filterText) {
return new Specification<VendorEmail>() {
@Override
public Predicate toPredicate(Root<VendorEmail> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
Predicate predicate = criteriaBuilder.conjunction();
predicate = criteriaBuilder.equal(root.get("user"), AuthUserThread.getContext());
if(!StringUtils.isEmpty(filterText)) {
Predicate toPredicate = criteriaBuilder.like(root.get("to"), "%" + filterText + "%");
Predicate fromPredicate = criteriaBuilder.like(root.get("from"), "%" + filterText + "%");
Predicate subjectPredicate = criteriaBuilder.like(root.get("subject"), "%" + filterText + "%");
Predicate messagePredicate = criteriaBuilder.like(root.get("message"), "%" + filterText + "%");
Predicate orPredicate = criteriaBuilder.or(toPredicate, fromPredicate, subjectPredicate, messagePredicate);
predicate = criteriaBuilder.and(predicate, orPredicate);
return predicate;
}
predicate = criteriaBuilder.and(predicate);
return predicate;
}
};
}
}
英文:
I solve this problem in another way -
public class VendorEmailSpecification {
public static Specification<VendorEmail> filter(String filterText) {
return new Specification<VendorEmail>() {
@Override
public Predicate toPredicate(Root<VendorEmail> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
Predicate predicate = criteriaBuilder.conjunction();
predicate = criteriaBuilder.equal(root.get("user"), AuthUserThread.getContext());
if(!StringUtils.isEmpty(filterText)) {
Predicate toPredicate = criteriaBuilder.like(root.get("to"), "%"+filterText+"%");
Predicate fromPredicate = criteriaBuilder.like(root.get("from"), "%"+filterText+"%");
Predicate subjectPredicate = criteriaBuilder.like(root.get("subject"), "%"+filterText+"%");
Predicate messagePredicate = criteriaBuilder.like(root.get("message"), "%"+filterText+"%");
Predicate orPredicate = criteriaBuilder.or(toPredicate, fromPredicate, subjectPredicate, messagePredicate);
predicate = criteriaBuilder.and(predicate, orPredicate);
return predicate;
}
predicate = criteriaBuilder.and(predicate);
return predicate;
}
};
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论