gpt4 book ai didi

java - 如何使用 JPA CriteriaBuilder selectCase() 以便它可以将 Predicate 作为结果?

转载 作者:行者123 更新时间:2023-12-02 09:38:27 35 4
gpt4 key购买 nike

我需要实现一个条件查询,其中包含 if...then...else 场景。我发现 javax.persistence.criteria.CriteriaBuilder.selectCase() 适合此目的。它返回一个 Expression 作为结果。

要运行条件查询,我需要使用接受谓词数组的 where() 。这是因为我有多个谓词要包含在查询中。

现在,由于 selectCase() 返回 Expression,我无法将其与现有谓词列表集成。

Type mismatch: cannot convert from Expression<Object> to Predicate

如何使用 selectCase() 才能将谓词作为结果?或者还有其他更好的方法吗?

示例:

为了说明这个问题,我有以下实现“默认情况下,获取来自印度的所有特定年龄的用户(来自特定国家和城市)”

如果...则...否则场景

如果来自特定国家

   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 中的谓词没有可以返回的内在 boolean 值。用 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

关于java - 如何使用 JPA CriteriaBuilder selectCase() 以便它可以将 Predicate 作为结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57309212/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com