2

次のデータベース モデルがあります。

A
aId

AB
aId
bId

B
bId
status

Spring データ仕様では、B.status が 'X' の場合に A のインスタンスを返したいと考えています。JPQLコードは次のとおりです。

select a from A a where a in
     (select ab.id.a from AB ab where ab.id.b.status= :status)

モデル クラスは次のとおりです。

@Entity
public class A {
     private Long aId;

     @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "id.a")
     private Set<AB> ab;
}

@Entity
public class B {
     private Long bId;
     private String Status;

     @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "id.b")
     private Set<AB> ab;
}

@Entity
public class AB {
     private ABPK id;
}

public class ABPK {
     @ManyToOne
     @JoinColumn(name="aId")
     private A a;

     @ManyToOne
     @JoinColumn(name="bId")
     private B b;
}

Spring仕様のJPA基準はどうなりますか?

public class ASpecifications {
     public static Specification<A> test(final String status) {
          return new Specification<Party>() {
          @Override
          public Predicate toPredicate(Root<A> a, CriteriaQuery<?> query, CriteriaBuilder cb) {
            return null;
          }
        };
     }
}
4

4 に答える 4

3

Criteria API を使用して A のインスタンスを返す仕様は次のとおりです。

public class ASpecifications {
     public static Specification<A> test(final String status) {
          return new Specification<Party>() {
          @Override
          public Predicate toPredicate(Root<A> a, CriteriaQuery<?> query, CriteriaBuilder cb) {
            Subquery<A> sq = query.subquery(A.class);
            Root<AB> ab = sq.from(AB.class);
            sq.select(ab.get(AB_.id).get(ABPK_.a));
            sq.where(cb.equal(ab.get(AB_.id).get(ABPK_.b).get(B_.status), status));

            Predicate p = cb.in(a).value(sq);
            return cb.and(p);
          }
        };
     }
}
于 2012-06-04T14:56:11.200 に答える
0

ここで達成しようとしていることを正確に説明する前の投稿にいくつかの良い例が含まれています: jpa-2-0-criteria-api-subqueries-in-expressions

于 2012-06-01T23:18:06.190 に答える
0

「Bが提供されたステータスであるABエンティティからのAエンティティ」を選択したいと思います。

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<A> cq = cb.createQuery(A.class);
Root<AB> ab = cq.from(AB.class);
cq.select(ab.get("id").get("a"));
cq.where(cb.equal(ab.get("id").get("b.status"), status));
于 2012-06-04T12:51:32.143 に答える
0

Select In - オプションですが、二重結合でも同じ結果が得られます。そして、そのような jpa 仕様を作成する方が簡単です:
SELECT A.ID FROM A LEFT JOIN AB ON A.ID = AB.A_ID LEFT JOIN B ON AB.B_ID = B.ID WHERE B.STATUS = 'STATUS'
メソッドは次のようになります:

public static Specification<A> findB(String input) {
    return new Specification<A>() {
        @Override
        public Predicate toPredicate(Root<A> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
            Join<A,AB> AjoinAB = root.joinList(A_.AB_LIST,JoinType.LEFT);
            Join<AB,B> ABjoinB = AjoinAB.join(AB_.B,JoinType.LEFT);
            return cb.equal(ABjoinB.get(B_.NAME),input);
        }
    };
}

またはそれより短い

public static Specification<A> findB(String input) {
    return (Specification<A>) (root, cq, cb) -> {
        Join<A,AB> AjoinAB = root.joinList(A_.AB_LIST,JoinType.LEFT);
        Join<AB,B> ABjoinB = AjoinAB.join(AB_.B,JoinType.LEFT);
        return cb.equal(ABjoinB.get(B_.NAME),input);
    };
}

この質問が出てから長い時間が経っていることは知っていますが、同じことをしようとしたときに出くわしました。これが機能する私のソリューションであり、誰かに役立つことを願っています。

以下のエンティティ

@Entity
public class A {
    @Id
    private Long id;
    private String name;
    @OneToMany(mappedBy = "a")
    private List<AB> abList;
}
@Entity
public class B {
    @Id
    private Long id;
    private String status;
    @OneToMany(mappedBy = "b")
    private List<AB> abList;
}
@Entity
public class AB {
    @Id
    private Long id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "a_id")
    private A a;
    @ManyToOne
    @JoinColumn(name = "b_id")
    private B b;
}
于 2020-02-29T10:58:46.957 に答える