JPAの複雑なマルチテーブルのクエリ

最近の研究は、Hibernate + JPAのための要件は単純なクエリ、JPA継承CrudRepositoryインターフェースで、データベースと対話して、仕様JPQLクエリを命名JPAメソッドを使用しますが、複雑なクエリを実行する際に、継承する必要JpaSpecificationExecutorインタフェースは仕様を利用理由だけで行わ私自身は、この問題が発生したため、複雑なクエリのために、方法があるものの、多くの情報をチェックしますが、この方法が便利で、複雑なクエリJPA良く使用することができないことを知っているために、詳細な説明はありません。私はあなたにいくつかの栗を与えるだろう、私自身の使用JPAマルチテーブルについての話の詳細は、複雑なシーンやアイデアを照会します。

栗1:

Userエンティティクラスにいくつかのプロパティで上映。

1. 名字
2. ID
3. 手机号

この条件は、複雑なクエリの単一のテーブルを超えている、それはいくつかのプロパティでスクリーニングされているので、あなただけの仕様クエリを使用する必要があるので、どのように多くの知らないプロパティの数は簡単にこの要求を達成することができます。:以下のコードを参照してください
、ページ上でユーザーのクエリのリストを条件によるフィルタ:シーン

ID、私は設定ページ上の3つの条件がsearchName、searchId、searchMobileありました。これはuserRepositoryがJpaSpecificationExecutorインタフェースを継承したように、ユーザ・テーブルであるため、私は、クラスのパッケージ状態を作成しました

public class PageParam<T> {
    private Integer pageSize = 10;
    private Integer pageNumber = 1;
    private String searchName;
    private String searchMobile;
    private String searchId;
}

この方法は、ページ番号のpageSizeので、ダイレクトIタブであり、以下の3つのパラメータ、主としてカプセル、受信パラメータを容易にするため、このカテゴリに直接書き込むことができるので

Specification<T> specification = new Specification<T>() {

    @Override
    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        List<Predicate> list = new ArrayList<Predicate>();

        if (StringUtils.isNotBlank(searchName)) {
            list.add(cb.like(root.get("name").as(String.class), "%" + searchName + "%"));
        }

        if (StringUtils.isNotBlank(searchId)) {
            list.add(cb.equal(root.get("id").as(Long.class), searchId));
        }

        if (StringUtils.isNotBlank(searchMobile)) {
            list.add(cb.like(root.get("mobile").as(String.class), "%" + searchMobile + "%"));
        }

        Predicate[] p = new Predicate[list.size()];
        return cb.and(list.toArray(p));
    };
};

ここでは、テーブルである、なぜなら限り3回言って良い、プロパティ名のプロパティ名重要なものの属性をチェックするためにNに対応する名前のroot.get(「N」)など。
マルチテーブルクエリのセットで、次の見

栗2:

4つのテーブルがあります。

public class Living {
    Long id;
    
    @ManyToOne
    @JsonIgnore
    @JoinColumn(name = "actorId", foreignKey = @ForeignKey(name = "none", value =ConstraintMode.NO_CONSTRAINT))
    public Actor actor;
    
   @ManyToOne
    @JsonIgnore
    @JoinColumn(name = "regionId", foreignKey = @ForeignKey(name = "none", value =ConstraintMode.NO_CONSTRAINT))
    public Region region;
}
    
public class Actor {
    Long id;
    
    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }, fetch = FetchType.LAZY)
    @JoinColumn(name = "actorId")
    @org.hibernate.annotations.ForeignKey(name = "none")
    List<Living> livings = new ArrayList<>();
    
   @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }, fetch = FetchType.LAZY)
    @org.hibernate.annotations.ForeignKey(name = "none")
    @JoinColumn(name = "userDetailId", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
    UserDetail userDetail;
    
   @Column(nullable = false)
    @Enumerated(value = EnumType.ORDINAL)
    ActorType actorType = ActorType.A;
    
    public enum ActorType{
        A,B,C
    }
}
    
public class UserDetail {
    Long id; 
    
   @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }, fetch = FetchType.LAZY)
    @org.hibernate.annotations.ForeignKey(name = "none")
    @JoinColumn(name = "actorId", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
    Actor actor;
    
    String truename;
}
    
public class Region {
    Long id;
    
    String name;
    
    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH }, fetch = FetchType.LAZY)
    @JoinColumn(name = "regionId")
    @org.hibernate.annotations.ForeignKey(name = "none")
    List<Living> Livings;
}
    

今、私たちは地域のセックス俳優としてだけでなく、IDのactortypeのuserdetai種類に応じた条件を満たすように生活条件をチェックアウトしたいです。

public class PageParam<Living> {
    private Integer pageSize = 10;
    private Integer pageNumber = 1;
    private Sex sex;
    private ActorType actortype;
    private Long cityid;

これは、次のクエリに複数のテーブルが含まれるため、単一のテーブルのクエリ上記の例では、もはや適しているので、まず、私はまだ、私が直接あなたが望む結果一般的なクエリに与えられたようなクラスが、ここでは一般的なをカプセル化していませんこのクエリが、基準がモデルを提供してくれ方法に参加します

Specification<Living> specification = new Specification<Living>() {

    @Override
    public Predicate toPredicate(Root<Living> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        List<Predicate> list = new ArrayList<Predicate>();

        if (null!=sex) {
            Join<UserDetail, Living> join = root.join("actor", JoinType.LEFT);
            list.add(cb.equal(join.get("userDetail").get("sex"),  sex ));
        }

        if (null!=actortype) {
            Join<Actor, Living> join = root.join("actor", JoinType.LEFT);
            list.add(cb.equal(join.get("actorType"),  actortype));
        }
        if (null!=cityid) {
            Join<Region, Living> join = root.join("region", JoinType.LEFT);
            list.add(cb.equal(join.get("id"), cityid));
        }

        //Join<A, B> join = root.join("bs", JoinType.LEFT);
        //list.add(cb.equal(join.get("c").get("id"), id));
        Predicate[] p = new Predicate[list.size()];
        return cb.and(list.toArray(p));
    };
};

ここでは、パッケージの私の条件があります。複数のクエリ条件JPA方法は、主に、我々は提供するカプセル化条件の基準をベースにしており、位置定義された条件に応じて、クエリが完了した後、SQL文を生成します。
私は、一例として、以下の文で、このマルチテーブルクエリ内の場所を言わなければなりません

Join<UserDetail, Living> join = root.join("actor", JoinType.LEFT);
list.add(cb.equal(join.get("userDetail").get("sex"),  sex ));

jointype.LEFT主な点は、このプロパティは、「俳優」の前で、そのような私が与える例の生体照会テーブルからクエリの最初のステップは、俳優に住んでチェックアウトすることであることを特徴としながら、最終的なテーブルであることですその後、俳優の後にそう次join.get(「userDetail」)でuserdetailプロパティuserdetailでのセックスがある。取得 (「性別」)、 これはあなたが所望の特性を得るまで、対応する属性から抜け出すです。次の2つの属性が同じトークン、ある
多くの人々のJPA私もそう思う前に、MyBatisのクエリとして、JPAマルチテーブル、マルチ複雑なクエリ条件という大きな誤解がありますが、以来、JPAすることによって、これを達成マルチテーブルクエリと、より複雑な条件の後、私はそれが複雑なクエリに劣っていないと思いMyBatisの休止状態より高い閾値はJPA休止状態休止状態だけしきい値をするために必要な低下かもしれないが、特にSQL文は、非常に熟練したコードの農家ではありません、私はあなたを願っていますこれは、より簡単に私の経験を介してデータベースと対話することができます。

おすすめ

転載: www.cnblogs.com/alterem/p/11295358.html