0

给定以下实体:

@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<>();

}

因此,订阅可以有零个或多个 mainCode 或它感兴趣的 otherCode。我可以获取经过的某个对象的 mainCode 和 otherCode。代码本身是可嵌入的,只有单个字符串字段。

如何创建一个 JPA 查询(或 CriteriaBuilder),它使用“或”机制在这些集合中进行搜索?

所以基本上我正在寻找这样的查询:

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,如果它没有任何 otherCode,它也会失败。

4

1 回答 1

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
于 2015-04-14T14:14:56.757 回答