欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JPA的多表復(fù)雜查詢的方法示例

 更新時間:2019年08月04日 09:36:19   作者:alterem  
這篇文章主要介紹了JPA的多表復(fù)雜查詢的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

最近工作中由于要求只能用hibernate+jpa 與數(shù)據(jù)庫進行交互,在簡單查詢中,jpa繼承CrudRepository接口 ,然后利用jpa的方法命名規(guī)范進行jpql查詢,然而在進行復(fù)雜查詢時,需要繼承JpaSpecificationExecutor接口 利用Specification 進行復(fù)雜查詢,由于我自己就遇到了這一問題,查了好多資料,雖然有方法,但是都沒有一個詳細的講解,以至于知道方法而不能很好的利用jpa復(fù)雜查詢的方便之處。我將舉幾個栗子,來詳細的說一下我自己在使用jpa多表復(fù)雜查詢的場景和想法。
栗子1:

以一個實體類User中的幾個屬性進行篩選。

1. 名字
2. ID
3. 手機號
這是一個單表的多條件復(fù)雜查詢,由于是在幾個屬性中進行篩選,其中的屬性的個數(shù)不知道有多少個,所以只需要利用Specification 查詢就可以很方便的實現(xiàn)這個需求。 下面請看代碼:
場景:頁面上通過條件篩選,查詢用戶列表

這里有3個條件 在頁面上我設(shè)置的id分別為searchName,searchId,searchMobile。 由于這個是user表 所以userRepository 繼承JpaSpecificationExecutor接口,隨后我創(chuàng)建了一個封裝條件的類

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

由于我這個方法是直接分頁的 所以pageNumber 和pageSize 也可以直接寫入到這個類中,用于方便接收參數(shù),主要是對下面3個參數(shù)的封裝

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

這里因為都是一個表,所以只要root.get(‘N ‘)這個N對應(yīng)所要查的 屬性的名字就好,屬性名 屬性名 重要的事情說三遍。
再接下來看一組多表的查詢

栗子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;
}

現(xiàn)在要根據(jù)userdetai 種的 sex actor中的actortype 還有 region的id 為條件查詢出滿足條件的living。

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

首先我還是封裝了這樣一個類,但是這里的泛型 我是直接給到了想要的查詢結(jié)果的泛型,接下來 因為這里涉及到了一個 多表的查詢 所以上面的單表查詢的例子 已經(jīng)不適合這個查詢了,但是Criteria 的join方法 給我們提供了一個模式

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 的多條件查詢 主要是根據(jù)Criteria 為我們提供的方法封裝條件,然后根據(jù) 給條件定義的位置,再生成sql語句,之后完成查詢。

不得不說的地方,在這個多表的查詢中以下面這句為例

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

jointype.LEFT主要是說最終的這個屬性 是在哪個表中, 而前面的 “actor” 則表示 從living表中 查詢的 第一步的查詢,比如我給出的例子 是要查詢出 living 中的 actor 然后是actor 中的userdetail 之后才是 userdetail中的 sex屬性 所以下面的join.get(“userDetail”).get(“sex”) ,這里就是get出相應(yīng)的屬性,一直到你得到想要的屬性為止。 接下來的兩個屬性 也同理,許多人多jpa 有很大的誤解,認為jpa 的多表,多條件復(fù)雜查詢,不如mybatis的查詢,在之前我也是這么覺得,但自從通過jpa 實現(xiàn)了這個多表多條件的復(fù)雜查詢之后,我覺得hibernate的復(fù)雜查詢 不遜于mybatis ,尤其是對sql 語句不是很精通的 碼農(nóng),雖然hibernate的門檻較高可jpa 恰恰降低了hibernate 所需要的門檻,希望大家可以通過我的經(jīng)驗,更方便的與數(shù)據(jù)庫進行交互。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Maven引用自定義jar包方式

    Maven引用自定義jar包方式

    這篇文章主要介紹了Maven引用自定義jar包方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 使用@ConfigurationProperties實現(xiàn)類型安全的配置過程

    使用@ConfigurationProperties實現(xiàn)類型安全的配置過程

    這篇文章主要介紹了使用@ConfigurationProperties實現(xiàn)類型安全的配置過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 解決idea中debug工具欄消失后如何顯示的問題

    解決idea中debug工具欄消失后如何顯示的問題

    這篇文章主要介紹了解決idea中debug工具欄消失后如何顯示的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • 解決在IDEA中創(chuàng)建多級package的問題

    解決在IDEA中創(chuàng)建多級package的問題

    這篇文章主要介紹了解決在IDEA中創(chuàng)建多級package的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • 如何利用java中String類的substring()字符串截取最后一個字符

    如何利用java中String類的substring()字符串截取最后一個字符

    Java中的String是不可變的類型,因此substring()方法并不會改變原字符串,而是返回了一個新的字符串,這篇文章主要介紹了如何利用java中String類的substring()字符串截取最后一個字符,需要的朋友可以參考下
    2023-11-11
  • 簡單談?wù)凴xJava和多線程并發(fā)

    簡單談?wù)凴xJava和多線程并發(fā)

    認識RxJava已經(jīng)有一段時間了,但是一直沒有機會在項目中嘗試,最近在新的項目里引進了RxJava寫一些事件處理,在review代碼的時候發(fā)現(xiàn)了一些和多線程并發(fā)相關(guān)的問題,所以寫了這篇文章,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-03-03
  • Java的幾個重要版本_動力節(jié)點Java學院整理

    Java的幾個重要版本_動力節(jié)點Java學院整理

    jdk8 將在2014年3月份發(fā)布,迄今為止,可能是最大更新的java版本,也是令人期待的一個版本,在Java中引入閉包概念對Java程序開發(fā)方法的影響甚至會大于Java5中引入的泛型特征對編程方式帶來的影響
    2017-06-06
  • 如何更優(yōu)雅的關(guān)閉java文本、網(wǎng)絡(luò)等資源

    如何更優(yōu)雅的關(guān)閉java文本、網(wǎng)絡(luò)等資源

    這篇文章主要介紹了如何更優(yōu)雅的關(guān)閉java文本、網(wǎng)絡(luò)等資源,在 finally 的關(guān)閉代碼中,還要再來一個 try/catch,看著是不是很難受,很不優(yōu)雅,很想干掉這個 finally!,需要的朋友可以參考下
    2019-06-06
  • Jlabel實現(xiàn)內(nèi)容自動換行簡單實例

    Jlabel實現(xiàn)內(nèi)容自動換行簡單實例

    這篇文章主要介紹了Jlabel實現(xiàn)內(nèi)容自動換行簡單實例,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • SpringCloud feign微服務(wù)調(diào)用之間的異常處理方式

    SpringCloud feign微服務(wù)調(diào)用之間的異常處理方式

    這篇文章主要介紹了SpringCloud feign微服務(wù)調(diào)用之間的異常處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06

最新評論