本文介紹了如何使用JPA CriteriaBuilder seltCase()使其可以有謂詞作為結(jié)果?的處理方法,對(duì)大家解決問(wèn)題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧!
問(wèn)題描述
我需要實(shí)現(xiàn)一個(gè)具有If…Then…Else方案的條件查詢。
我發(fā)現(xiàn)javax.persistence.criteria.CriteriaBuilder.selectCase()
適合于此目的。它返回Expression
作為結(jié)果。
要運(yùn)行條件查詢,我需要使用接受謂詞數(shù)組的where()
。這是因?yàn)槲矣卸鄠€(gè)謂詞要包含在查詢中。
現(xiàn)在,由于selectCase()
返回Expression
,我無(wú)法將其與現(xiàn)有謂詞列表集成。
Type mismatch: cannot convert from Expression<Object> to Predicate
如何使用selectCase()使我可以將謂詞作為結(jié)果?
或任何其他更好的方法來(lái)完成此操作?
示例:
為了說(shuō)明這個(gè)問(wèn)題,我有以下實(shí)現(xiàn):”默認(rèn)情況下,從印度獲取所有特定年齡的用戶和(來(lái)自特定國(guó)家和城市的)其他用戶”
If…Then…Else方案
如果來(lái)自特定國(guó)家
if from particular city
否則
if from "India"
//查詢實(shí)現(xiàn)
@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);
}
//User.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;
...
//Address.java
@Embeddable
public class Address {
private String city;
private String country;
...
推薦答案
如果我沒看錯(cuò)您的問(wèn)題,您需要以下邏輯:
IF is_user_from_country
RETURN is_user_from_city
ELSE
RETURN is_user_from_india
將其轉(zhuǎn)換為查詢很困難,因?yàn)镾QL中的謂詞沒有可以返回的內(nèi)在布爾值。在SQL術(shù)語(yǔ)中,它將如下所示:
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中(注意,我還沒有測(cè)試過(guò),可能有語(yǔ)法錯(cuò)誤):
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
語(yǔ)句。如果不是,您可以嘗試使邏輯更直接:
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
這篇關(guān)于如何使用JPA CriteriaBuilder seltCase()使其可以有謂詞作為結(jié)果?的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,