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

}

そのため、Subscription は、関心のある 0 個以上の mainCode または otherCode を持つことができます。通過する特定のオブジェクトの mainCode および otherCode を取得できます。コード自体は、単一の String フィールドのみを持つ埋め込み可能です。

「OR」メカニズムを使用してこれらのコレクションを検索する 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 に答える