How to get an interesect query using CritieraQuery?

纵饮孤独 提交于 2019-12-06 12:47:39

问题


Given

 @Entity
 public class Document {

    @Id
    @Column(name = "DOCUMENT_ID")
    private Long id;

    @ElementCollection
    @CollectionTable(
       name="TAG",
       joinColumns=@JoinColumn(name="DOCUMENT_ID")
    )
    @Column(name="TAG")
    private Set<String> tags;    
 }

find all documents tagged with a specific collection of tags. Essentially, an EclipseLink equivalent of:

SELECT d FROM Document d WHERE :tag1 MEMBER OF d.tags
INTERSECT
SELECT d FROM Document d WHERE :tag2 MEMBER OF d.tags
...
SELECT d FROM Document d WHERE :tagn MEMBER OF d.tags

but using a JPA CritieraQuery.


回答1:


Use an aggregate query with a having clause to select rows that matched all the required tags:

    CriteriaBuilder cb = entityManager().getCriteriaBuilder();
    CriteriaQuery<Long> q = cb.createQuery(Long.class);
    Root<Document> from = q.from(Document.class);
    List<Predicate> predicates = new ArrayList<Predicate>();
    Expression<Long> id = from.get("id");

    Expression<Collection<String>> documentTags = from.get("tags");
    for (String tag : searchedTags) {
        Expression<String> param = cb.literal(tag);
        Predicate predicate = cb.isMember(param, documentTags);
        predicates.add(predicate);
    }

    q.multiselect(id).where(
            cb.or(predicates.toArray(new Predicate[0])));
    q.distinct(true);
    q.groupBy(id);

    q.having(cb.equal(cb.count(id), searchedTags.size()));

    TypedQuery<Long> query = entityManager().createQuery(q);


来源:https://stackoverflow.com/questions/15690791/how-to-get-an-interesect-query-using-critieraquery

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!