【问题标题】:How to do a search with multiple ElementCollections如何使用多个 ElementCollections 进行搜索
【发布时间】:2015-06-20 01:50:35
【问题描述】:

给定以下实体:

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

【问题讨论】:

  • 您的查询有什么问题?

标签: jpa criteria jpql embeddable


【解决方案1】:

在您的示例中,情况与此相反。 例如,如果代码具有 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

【讨论】:

  • 在编辑中使用左关节。我没有使用标准,但有等效的构造。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-29
  • 1970-01-01
  • 1970-01-01
  • 2014-11-13
  • 2019-07-19
  • 2021-12-24
相关资源
最近更新 更多