鉴于以下实体:
@Entity
@Table(name = "subscription")
public class Subscription implements Serializable {
private static final long serialVersionUID = 1L;
@ElementCollection
@CollectionTable(joinColumns= @JoinColumn(name="subscription"))
private Set<Code> mainCodes = new HashSet<>();
@ElementCollection
@CollectionTable(joinColumns= @JoinColumn(name="subscription"))
private Set<Code> otherCodes = new HashSet<>();
}
因此,订阅可以包含零个或多个它感兴趣的mainCodes或其他代码。我可以获取经过的某个对象的mainCode和otherCode。代码本身是可嵌入的,只有一个字符串字段。
如何创建一个JPA查询(或CriteriaBuilder),使用“OR”机制在这些集合中搜索?
所以基本上我正在寻找这样的查询:
select s from subscription s where :myMainCode IN s.mainCodes OR :otherCode IN s.otherCodes
使用CriteriaBuilder是可行的,还是需要使用更明确的查询?如果是这样,查询是什么样的?
编辑:尝试使用CriteriaBuilder:
final CriteriaBuilder cb = this.entityManager.getCriteriaBuilder();
final CriteriaQuery<Subscription> cq = cb.createQuery(Subscription.class);
final Root<Subscription> root = cq.from(Subscription.class);
final Expression<Collection<Code>> mainCodes = root.get("mainCodes");
final Predicate containsMainCode = cb.isMember(obj.getClassCode(), mainCodes);
final Expression<Collection<Code>> otherCodes = root.get("otherCodes");
final Predicate containsOtherCode = cb.isMember(obj.getOtherCode(), otherCodes);
final Predicate searchPredicate = cb.or(containsMainCode, containsOtherCode);
cq.select(root).where(searchPredicate);
但是,这会创建两个涉及的集合的内部联接,这意味着如果mainCode有一行,它将不返回任何结果,但是对于数据库中的otherCode则不会返回结果,它会生成此查询:
SELECT t0.ID
FROM Subscription_OTHERCODES t2, Subscription_MAINCODES t1, subscription t0
WHERE ((t1.CODESYSTEM = ?) AND (t1.CODE = ?)) OR ((t2.CODESYSTEM = ?) AND (t2.CODE = ?))) AND ((t1.subscription = t0.ID) AND (t2.subscription = t0.ID))
因此即使找到匹配的mainCode,如果它没有任何其他的代码也会失败。
答案 0 :(得分:0)
在你的例子中,这是另一种方式。 例如,如果代码具有name属性):
select s from Subscription s left join s.mainCodes m left join s.otherCodes o
where m.name IN :myMainCode or o.name IN :myOtherCode