Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
313 views
in Technique[技术] by (71.8m points)

java - Criteria builder IN clause with nested query for embedded @ElementCollection

I have the User and Address entities (actually others but for simplify).

@Entity
public class User {
    @Id
    @GeneratedValue
    protected long id;
    ...

    @ElementCollection
    @CollectionTable(name = "address",
        joinColumns = {@JoinColumn(name = "user_id")})
    @Column(name = "street")
    private List<Address> addresses;

    ...
}

@Embeddable
public class Address {
    private String street;
    ...
}

How to make nested query for Address and use it in IN clause? Result query that I expect `select * from user u where u.id in (select user_id from address where street like '%Green%');

Root<User> root = ...; // Root query already exists

CriteriaQuery<Address> cq = builder.createQuery(Address.class);
Root<Address> addressRoot = cq.from(Address.class);

cq.select(addressRoot.get("user_id"))
    .where(
        builder.like(
            addressRoot.get("street"),
            "%Green%"
        )
    );

Predicate .... = criteriaQuery.where(root.get("id").in(cq))

I tried something like this, but it does not work - Address it is not entity and I can't create CriteriaQuery with it. Important note: I can't use root.join("addresses").get("street").like(...) for several reasons

question from:https://stackoverflow.com/questions/65942304/criteria-builder-in-clause-with-nested-query-for-embedded-elementcollection

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to use an exists subquery, something like the following:

Root<User> root = ...; // Root query already exists

CriteriaQuery<Address> cq = builder.createQuery(Address.class);
Subquery<Integer> subquery = cq.subquery(Integer.class);
Root<User> correlatedRoot = subquery.correlate(root);
Join<User, Address> addressRoot = correlatedRoot.join("addresses");

cq.select(addressRoot.get("user_id"));
subquery.where(
        builder.like(
            addressRoot.get("street"),
            "%Green%"
        )
    );

Predicate .... = criteriaQuery.where(builder.exists(subquery));

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...