JPA Criteria API - joining ElementCollection with WHERE condition on ElementCollection foreign key

Lukas S :

I have an entity Document and enum Label (not my real case, I am using analogy). The Document can have set of Labels. The mapping of labels is following:

@Entity
public class Document {
    ...

    @ElementCollection(fetch = FetchType.EAGER)
    @Enumerated(EnumType.STRING)
    @Column(name = "labels")
    private Set<Label> labels = new HashSet<>();

    ...
}

It means labels are mapped into separated table with two columns (document_id, value) but in Java it is just enum

I need to select Documents that DO NOT have any of listed labels. In SQL it looks like this:

select D.id 
from document D left join label L 
on D.id = L.document_id and L.value in('label1','label2',...)
where L.document_id is null

But I don't know how to write it in JPA Criteria API. I don't know how to express the foreign key in labels table. The JPA predicate should be something like this

CriteriaBuilder cd = ...
SetJoin<Object, Object> labelsJoin = root.joinSet("labels", JoinType.LEFT);
cb.and(labelsJoin .in("label1","label2"), cb.isNull(...???...)));

Here is my related SQL question

Thanks in advance for your suggestions. Lukas

alex valuiskyi :

This should return expected result, but query statement is a bit different

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Document> query = cb.createQuery(Document.class);
Root<Document> root = query.from(Document.class);

Subquery<Long> subquery = query.subquery(Long.class);
Root<Document> subRoot = subquery.from(Document.class);
Join<Document, Label> label = subRoot.join("labels", JoinType.INNER);

List<Label> labels = Arrays.asList(Label.LABEL_1, Label.LABEL_2);
subquery.select(subRoot.get("id")).where(
    cb.equal(root.get("id"), subRoot.get("id")), 
    label.in(labels)
);

query.select(root).where(cb.exists(subquery).not());

List<Document> result = entityManager.creteQuery(query).getResultList();

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=352947&siteId=1