【问题标题】:Selecting an entity by collection set equality通过集合集相等性选择实体
【发布时间】:2014-04-13 01:46:12
【问题描述】:

我正在尝试执行执行以下操作的 JPQL 查询或 JPA 操作。我有一个元素,它由字符串的元素集合组成:

@Entity(name="REQUEST")
public class Request {

    @ElementCollection
    private Set<String> keywords;
    ...    
}

我希望能够选择关键字与给定字符串集完全匹配的实体。我已经研究过使用 IN 但如果只存在一个关键字,那将匹配。只在所有关键字都存在的情况下如何匹配?

【问题讨论】:

  • 那么你想设置相等还是匹配“仅当所有关键字都存在时”?这是两个不同的东西。例如,在给定输入 [A, B, C] 的情况下,查询是否应该返回带有关键字 [A, B, C, D] 的 Request
  • 不,它应该只返回一个具有完全相同关键字集的请求。

标签: jakarta-ee jpa jpql


【解决方案1】:

我能想到的最简单的方法是进行两次计数查询:

  1. 集合中关键字的数量统计
  2. 不在集合中的关键字的计数

#1 的结果应该等于集合中关键字的数量。 #2 的结果应该等于 0。例如:

List<Request> requests = 
  em.createQuery("select r from Request r " +
                 "where (select count(k1) from Request r1 " +
                 "       join r1.keywords k1 " +
                 "       where r1 = r and k1 in :keywords) = :numKeywords " +
                 "and (select count(k2) from Request r2 " +
                 "     join r2.keywords k2 " +
                 "     where r2 = r and k2 not in :keywords) = 0", Request.class)
     .setParameter("keywords", keywords)
     .setParameter("numKeywords", keywords.size())
     .getResultList();

如果您只关心该集合是否是请求关键字的子集,则不需要第二次计数。这可以通过以下方式在单个查询中完成:

List<Request> requests = 
      em.createQuery("select r from Request r " +
                     "join r.keywords k " +
                     "where k in :keywords " +
                     "group by r " +
                     "having count(r) = :numKeywords", Request.class)
        .setParameter("keywords", keywords)
        .setParameter("numKeywords", keywords.size())
        .getResultList();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-17
    • 2014-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多