<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          jpa多條件查詢重寫Specification的toPredicate方法

          共 5743字,需瀏覽 12分鐘

           ·

          2020-09-16 07:38

          點擊上方藍色字體,選擇“標星公眾號”

          優(yōu)質(zhì)文章,第一時間送達

          ? 作者?|??sandea??

          來源 |? ?urlify.cn/uYBFfa

          66套java從入門到精通實戰(zhàn)課程分享?

          Spring Data JPA支持JPA2.0的Criteria查詢,相應(yīng)的接口是JpaSpecificationExecutor。Criteria 查詢:是一種類型安全和更面向?qū)ο蟮牟樵?。

          這個接口基本是圍繞著Specification接口來定義的, Specification接口中只定義了如下一個方法:

          Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb);

          要理解這個方法,以及正確的使用它,就需要對JPA2.0的Criteria查詢有一個足夠的熟悉和理解,因為這個方法的參數(shù)和返回值都是JPA標準里面定義的對象。

          Criteria查詢基本概念

          Criteria 查詢是以元模型的概念為基礎(chǔ)的,元模型是為具體持久化單元的受管實體定義的,這些實體可以是實體類,嵌入類或者映射的父類。

          CriteriaQuery接口:代表一個specific的頂層查詢對象,它包含著查詢的各個部分,比如:select 、from、where、group by、order by等注意:CriteriaQuery對象只對實體類型或嵌入式類型的Criteria查詢起作用?
          Root接口:代表Criteria查詢的根對象,Criteria查詢的查詢根定義了實體類型,能為將來導航獲得想要的結(jié)果,它與SQL查詢中的FROM子句類似

          1:Root實例是類型化的,且定義了查詢的FROM子句中能夠出現(xiàn)的類型。

          2:查詢根實例能通過傳入一個實體類型給 AbstractQuery.from方法獲得。

          3:Criteria查詢,可以有多個查詢根。

          4:AbstractQuery是CriteriaQuery 接口的父類,它提供得到查詢根的方法。CriteriaBuilder接口:用來構(gòu)建CritiaQuery的構(gòu)建器對象Predicate:一個簡單或復雜的謂詞類型,其實就相當于條件或者是條件組合。

          Criteria查詢基本對象的構(gòu)建

          1:通過EntityManager的getCriteriaBuilder或EntityManagerFactory的getCriteriaBuilder方法可以得到CriteriaBuilder對象2:通過調(diào)用CriteriaBuilder的createQuery或createTupleQuery方法可以獲得CriteriaQuery的實例

          3:通過調(diào)用CriteriaQuery的from方法可以獲得Root實例過濾條件

          A:過濾條件會被應(yīng)用到SQL語句的FROM子句中。在criteria 查詢中,查詢條件通過Predicate或Expression實例應(yīng)用到CriteriaQuery對象上。

          B:這些條件使用 CriteriaQuery .where 方法應(yīng)用到CriteriaQuery 對象上

          C:CriteriaBuilder也作為Predicate實例的工廠,通過調(diào)用CriteriaBuilder 的條件
          方( equalnotEqual, gt, ge,lt, le,between,like等)創(chuàng)建Predicate對象。

          D:復合的Predicate 語句可以使用CriteriaBuilder的and, or andnot 方法構(gòu)建。

          構(gòu)建簡單的Predicate示例:
          Predicate?p1=cb.like(root.get(“name”).as(String.class),?“%”+uqm.getName()+“%”);

          ????????????Predicate?p2=cb.equal(root.get("uuid").as(Integer.class),?uqm.getUuid());

          ????????????Predicate?p3=cb.gt(root.get("age").as(Integer.class),?uqm.getAge());

          ????????構(gòu)建組合的Predicate示例:

          ???????????Predicate?p?=?cb.and(p3,cb.or(p1,p2));

          下面我們用兩個示例代碼來更深入的了解:

          1.復雜條件多表查詢
          //需要查詢的對象
          public?class?Qfjbxxdz?{
          ????@Id
          ????@GeneratedValue(generator?=?"system-uuid")
          ????@GenericGenerator(name?=?"system-uuid",?strategy?=?"uuid.hex")
          ????private?String?id;
          ????@OneToOne
          ????@JoinColumn(name?=?"qfjbxx")
          ????private?Qfjbxx?qfjbxx;?//關(guān)聯(lián)表
          ????private?String?fzcc;
          ????private?String?fzccName;
          ????@ManyToOne
          ????@JoinColumn(name?=?"criminalInfo")
          ????private?CriminalInfo?criminalInfo;//關(guān)聯(lián)表
          ????@Column(length=800)
          ????private?String?bz;
          ????//get/set......
          }
          ?
          //創(chuàng)建構(gòu)造Specification的方法
          //這里我傳入兩個條件參數(shù)因為與前段框架有關(guān),你們寫的時候具體自己業(yè)務(wù)自行決斷
          private?Specification?getWhereClause(final?JSONArray?condetion,final?JSONArray?search)?{
          ????????return?new?Specification()?{
          ????????????@Override
          ????????????public?Predicate?toPredicate(Root?root,?CriteriaQuery?query,?CriteriaBuilder?cb)?{
          ????????????????List?predicate?=?new?ArrayList<>();
          ????????????????Iterator?iterator?=?condetion.iterator();
          ????????????????Predicate?preP?=?null;
          ????????????????while(iterator.hasNext()){
          ????????????????????JSONObject?jsonObject?=?iterator.next();
          ????????????????????//注意:這里用的root.join 因為我們要用qfjbxx對象里的字段作為條件就必須這樣做join方法有很多重載,使用的時候可以多根據(jù)自己業(yè)務(wù)決斷
          ????????????????????Predicate?p1?=?cb.equal(root.join("qfjbxx").get("id").as(String.class),jsonObject.get("fzId").toString());
          ????????????????????Predicate?p2?=?cb.equal(root.get("fzcc").as(String.class),jsonObject.get("ccId").toString());
          ????????????????????if(preP!=null){
          ????????????????????????preP?=?cb.or(preP,cb.and(p1,p2));
          ????????????????????}else{
          ????????????????????????preP?=?cb.and(p1,p2);
          ????????????????????}
          ????????????????}
          ????????????????JSONObject?jsonSearch=(JSONObject)?search.get(0);
          ????????????????Predicate?p3=null;
          ????????????????if(null!=jsonSearch.get("xm")&&jsonSearch.get("xm").toString().length()>0){
          ???????????????????p3=cb.like(root.join("criminalInfo").get("xm").as(String.class),"%"+jsonSearch.get("xm").toString()+"%");
          ????????????????}
          ????????????????Predicate?p4=null;
          ????????????????if(null!=jsonSearch.get("fzmc")&&jsonSearch.get("fzmc").toString().length()>0){
          ????????????????????p4=cb.like(root.join("qfjbxx").get("fzmc").as(String.class),"%"+jsonSearch.get("fzmc").toString()+"%");
          ????????????????}
          ????????????????Predicate?preA;
          ????????????????if(null!=p3&&null!=p4){
          ????????????????????Predicate??preS?=cb.and(p3,p4);
          ????????????????????preA?=cb.and(preP,preS);
          ????????????????}else?if(null==p3&&null!=p4){
          ????????????????????preA=cb.and(preP,p4);
          ????????????????}else?if(null!=p3&&null==p4){
          ????????????????????preA=cb.and(preP,p3);
          ????????????????}else{
          ????????????????????preA=preP;
          ????????????????}
          ????????????????predicate.add(preA);
          ????????????????Predicate[]?pre?=?new?Predicate[predicate.size()];
          ????????????????query.where(predicate.toArray(pre));
          ????????????????return?query.getRestriction();
          ????????????}

          編寫DAO類或接口?

          dao類/接口 需繼承

          public?interface?JpaSpecificationExecutor

          接口;?
          如果需要分頁,還可繼承

          public?interface?PagingAndSortingRepositoryextends?Serializable>?extends?CrudRepository

          JpaSpecificationExecutor 接口具有方法

          Page findAll(Specification spec, Pageable pageable);?//分頁按條件查詢

          List findAll(Specification spec);?//不分頁按條件查詢

          方法。我們可以在Service層調(diào)用這兩個方法。?
          兩個方法都具有 Specification spec 參數(shù),用于設(shè)定查詢條件。?
          Service 分頁+多條件查詢 調(diào)用示例:

          studentInfoDao.findAll(new?Specification?()?{?
          ?
          ???public?Predicate?toPredicate(Root?root,?
          ?????CriteriaQuery?query,?CriteriaBuilder?cb)?{?
          ????Path?namePath?=?root.get("name");?
          ????Path?nicknamePath?=?root.get("nickname");?
          ????/**
          ?????????*?連接查詢條件,?不定參數(shù),可以連接0..N個查詢條件
          ?????????*/?
          ????query.where(cb.like(namePath,?"%李%"),?cb.like(nicknamePath,?"%王%"));?//這里可以設(shè)置任意條查詢條件?
          ?
          ????return?null;?
          ???}?
          ?
          ??},?page);?
          ?
          ?}?

          這里通過CriteriaBuilder 的like方法創(chuàng)建了兩個查詢條件, 姓名(name)字段必須包含“李”, 昵稱(nickname)字段必須包含“王”。?
          然后通過?
          連接多個查詢條件即可。這種方式使用JPA的API設(shè)置了查詢條件,所以不需要再返回查詢條件Predicate給Spring Data Jpa,故最后return null;即可。



          粉絲福利:108本java從入門到大神精選電子書領(lǐng)取

          ???

          ?長按上方鋒哥微信二維碼?2 秒
          備注「1234」即可獲取資料以及
          可以進入java1234官方微信群



          感謝點贊支持下哈?


          瀏覽 40
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美暗暗操| 四虎精品成人无码A片 | 日本一区二区三区免费观看 | 天堂8在线19 | 欧美 日韩 国产在线观看 |