java - 如何使用 JPA CriteriaBuilder selectCase() 以便它可以有 Predicate 作为结果?
问题描述
我需要实现一个具有 if...then...else 场景的条件查询。我发现javax.persistence.criteria.CriteriaBuilder.selectCase()
适合这个目的。它返回一个Expression
结果。
要运行条件查询,我需要使用where()
哪个接受谓词数组。这是因为我有多个谓词要包含在查询中。
现在,由于selectCase()
正在返回Expression
,我无法将它与现有的谓词列表集成。
Type mismatch: cannot convert from Expression<Object> to Predicate
如何使用 selectCase() 以便我可以将 Predicate 作为结果?或者有其他更好的方法吗?
例子:
为了说明这个问题,我有以下实现“默认情况下从印度获取所有特定年龄和(来自特定国家和城市)的用户”
如果...那么...其他情况
如果来自特定国家
if from particular city
别的
if from "India"
// 查询实现
@Override
public List<User> findUsersByAgeCountryAndCity(int age, String country, String city) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> user = cq.from(User.class);
List<Predicate> predicates = new ArrayList<>();
predicates.add(age(user, age));
predicates.add(country(user, country, city));
cq.where(predicates.toArray(new Predicate[0]));
return entityManager.createQuery(cq).getResultList();
}
private Predicate country(Root<User> user, String country, String city) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
return cb.selectCase() //
.when(cb.equal(user.get("address").get("country"), country),
cb.equal(user.get("address").get("city"), city))
.otherwise(cb.equal(user.get("address").get("country"), "India"));
}
private Predicate age(Root<User> entity, int age) {
return entityManager.getCriteriaBuilder().equal(entity.get("age"), age);
}
// 用户.java
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private LocalDate creationDate;
private LocalDate lastLoginDate;
private boolean active;
private int age;
@Column(unique = true, nullable = false)
private String email;
private Integer status;
@Embedded
private Address address;
@OneToMany
List<Possession> possessionList;
...
// 地址.java
@Embeddable
public class Address {
private String city;
private String country;
...
解决方案
如果我正确阅读了您的问题,您需要以下逻辑:
IF is_user_from_country
RETURN is_user_from_city
ELSE
RETURN is_user_from_india
将其放入查询中很棘手,因为 SQL 中的谓词没有可以返回的内在布尔值。在 SQL 术语中,它看起来像:
CASE
WHEN user.country = :country THEN
CASE WHEN user.city = :city THEN 1 ELSE 0 END
WHEN user.country = 'India' THEN 1
ELSE 0
END
在 Criteria API 中(注意我没有测试过,可能有语法错误):
cb.selectCase() //
.when(cb.equal(user.get("address").get("country"), country),
cb.selectCase()
.when(cb.equal(user.get("address").get("city"), city), cb.literal(true))
.otherwise(cb.literal(false))
))
.when(cb.equal(user.get("address").get("country"), "India"), cb.literal(true))
.otherwise(cb.literal(false));
不过,我并不完全确定 Criteria API 支持嵌套CASE
语句。如果没有,您可以尝试使逻辑更简单:
SELECT CASE
WHEN user.country = :country AND user.city = :city THEN TRUE
WHEN user.country = :country AND user.city <> :city THEN FALSE
WHEN user.country = 'India' THEN TRUE
ELSE FALSE
END
推荐阅读
- c# - 调用服务 URL
- java - Hibernate 在使用复合主键保存实体时抛出列索引超出预期范围
- timer - TIMER 触发 DMA - AD 转换,STM32F4 只工作一个
- java - Hystrix 拒绝 Completable Future 返回类型
- pydub - 尝试使用 Pydub 分割音频片段时出现 FileNotFoundError
- python - 有没有办法将属性应用于 PySide2 中的 QApplication 类?
- html - 在纯 CSS 中水平“拆分”元素,每半部分内容不同
- powerbi - 动态日期过滤器
- python - django 对象没有属性 status_code
- python - 使用 shutil move() 方法移动文件时出现 FileNotFoundError [Errno2]