1. 程式人生 > >Spring Data 與MongoDB 整合五:操作篇(分頁)

Spring Data 與MongoDB 整合五:操作篇(分頁)

一.簡介

     SpringData  MongoDB提供了org.springframework.data.mongodb.core.MongoTemplate對MongoDB的find的操作,我們上一篇介紹了基本文件的查詢,我們今天介紹分頁查詢,分頁查詢是返回到匹配文件的遊標,可以隨意修改查詢限制、跳躍、和排序順序的功能。

     我們在查詢時find()方法接受Query型別有org.springframework.data.mongodb.core.query和org.springframework.data.mongodb.core.query.BasicQuery

     Query類提供方法有limit、skip、sort查詢限制、跳躍、和排序順序的功能,BasicQuery繼承了Query類。

Query

Mongodb

說明

Query limit (int limit)

limit

方法是限制遊標返回結果的數量

Query skip (int skip)

skip

方法可以跳過指定值的條數,返回剩下的條數的結果,可以跟limit()方法進行組合可以實現分頁的效果

Sort sort () 已過時

現在是用query.with(sort)

sort

方法來對資料進行排序,根據指定的欄位,並使用1或-1來指定排序方式是升序或降序,類似於SQL的order by。

二.基本分頁

    Query類提供方法有limit、skip、sort查詢限制、跳躍、和排序順序的功能,我們實現Query查詢分頁

     第一步:實現分頁工具類

  1. /** 
  2.  * 分頁 
  3.  * @author zhengcy 
  4.  * 
  5.  * @param<T> 
  6.  */
  7. public classPageModel<T>{  
  8.     //結果集 
  9.    privateList<T> datas;   
  10.    //查詢記錄數 
  11.    privateintrowCount;   
  12.    //每頁多少條資料 
  13.    privateintpageSize=20;  
  14.    //第幾頁 
  15.    privateintpageNo=1;  
  16.    //跳過幾條數
  17.    privateintskip=0;   
  18.    /**
     
  19.      * 總頁數 
  20.      * @return 
  21.      */
  22.    publicintgetTotalPages(){   
  23.         return(rowCount+pageSize-1)/pageSize;   
  24.    }  
  25.    public List<T>getDatas() {  
  26.       return datas;  
  27.    }  
  28.    publicvoid setDatas(List<T>datas) {  
  29.       this.datas = datas;  
  30.    }  
  31.    publicint getRowCount() {  
  32.       return rowCount;  
  33.    }  
  34.    publicvoid setRowCount(int rowCount) {  
  35.       this.rowCount = rowCount;  
  36.    }  
  37.    publicint getPageSize() {  
  38.       return pageSize;  
  39.    }  
  40.    publicvoid setPageSize(int pageSize) {  
  41.       this.pageSize = pageSize;  
  42.    }  
  43.    publicint getSkip() {  
  44.       skip=(pageNo-1)*pageSize;  
  45.       return skip;  
  46.    }  
  47.    publicvoid setSkip(int skip) {  
  48.       this.skip = skip;  
  49.    }  
  50.    publicint getPageNo() {  
  51.       return pageNo;  
  52.    }  
  53.    publicvoid setPageNo(int pageNo) {  
  54.       this.pageNo = pageNo;  
  55.    }   
  56. }  

   第二步:實現分頁

  1. @Override
  2. public PageModel<Orders>getOrders(PageModel<Orders> page, DBObject queryObject,StringcollectionName) {  
  3.    Queryquery=newBasicQuery(queryObject);  
  4.    //查詢總數
  5.    int count=(int) mongoTemplate.count(query,Orders.class);  
  6.    page.setRowCount(count);  
  7.    //排序
  8.       query.with(new Sort(Direction.ASC, "onumber"));  
  9.      query.skip(page.getSkip()).limit(page.getPageSize());  
  10.    List<Orders>datas=mongoTemplate.find(query,Orders.class);  
  11.    page.setDatas(datas);  
  12.    return page;  
  13. }  

說明:

   Sort :sort () 已過時,現在是用query.with(sort),with引數是sort類

   Sort提供了幾種建構函式

      

   方法的描述

      (1)一個欄位的排序

          例如onumber欄位升序

        query.with(new Sort(Direction.ASC,"onumber"));

     (2)如果是多個欄位時同時升序或者降序時

       //排序

        query.with(new Sort(Direction.ASC,"a","b","c"));

   (3)不同的欄位按照不同的排序

  1. List<Sort.Order>orders=new ArrayList<Sort.Order>();  
  2. orders.add(newSort.Order(Direction.ASC, "a"));  
  3. orders.add(newSort.Order(Direction.DESC, "b"));  
  4. query.with(newSort(orders ));  

  a升序在按b降序

   第三步:測試類

  1. @Test
  2. publicvoid testList() throws ParseException  
  3. {  
  4.   PageModel<Orders>page=newPageModel<Orders>();  
  5.   page.setPageNo(1);  
  6.   page=ordersDao.getOrders(page, new BasicDBObject("cname","zcy"),collectionName);  
  7.   System.out.println("總數:"+page.getRowCount());  
  8.   System.out.println("返回條數:"+page.getDatas().size());  
  9.   System.out.println(JSONArray.fromObject(page.getDatas()));  
  10. }  

   查詢條件是cname=zcy

            

skip方法是跳過條數,而且是一條一條的跳過,如果集合比較大時(如書頁數很多)skip會越來越慢, 需要更多的處理器(CPU),這會影響效能。

三、進階的查詢分頁

      返回到匹配文件的遊標,可以隨意修改查詢限制、跳躍、和排序順序的功能,我們這邊對指標返回的結果,我用到Morphia框架。

       Morphia是一個開放原始碼的物件關係對映框架,它對MongoDB資料庫 Java版驅動進行了非常輕量級的物件封裝。我們需要通過DBCurosr獲取的DBObject轉換成我們對應的實體物件,方便我們操作實體。

     DBCurosr 是 DBCollection 的 find 方法返回的物件,可以設定 skip、limit 、sot等屬性執行分頁查詢

   第一步:在實體id要註解@id

      importcom.google.code.morphia.annotations.Id;

           @Id

         privateString id;

     @Id 註釋指示Morphia哪個欄位用作文件 ID

     如果沒加的話,會出現這樣的錯誤

    ...27 more

Caused by: com.google.code.morphia.mapping.validation.ConstraintViolationException: Number of violations: 1

NoId complained aboutcom.mongo.model.Orders. : No field is annotated with @Id; but it is required

    atcom.google.code.morphia.mapping.validation.MappingValidator.validate(MappingValidator.java:66)

    atcom.google.code.morphia.mapping.validation.MappingValidator.validate(MappingValidator.java:155)

    atcom.google.code.morphia.mapping.MappedClass.validate(MappedClass.java:259)

    atcom.google.code.morphia.mapping.Mapper.addMappedClass(Mapper.java:154)

    atcom.google.code.morphia.mapping.Mapper.addMappedClass(Mapper.java:142)

    atcom.google.code.morphia.Morphia.map(Morphia.java:55)

    atcom.mongo.dao.impl.OrdersDaoImpl.<init>(OrdersDaoImpl.java:37)

    atsun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

    atsun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)

    atsun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)

    atjava.lang.reflect.Constructor.newInstance(Unknown Source)

    atorg.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)

    ... 29more

  第二步:實現:

  1.    privateMorphia  morphia;  
  2.    public OrdersDaoImpl(){  
  3.       morphia= new Morphia();  
  4.       morphia.map(Orders.class);  
  5.    }  
  6.    @Override
  7.    public PageModel<Orders>getOrders(PageModel<Orders> page, DBObject queryObject,StringcollectionName) {  
  8.       DBObjectfilterDBObject=newBasicDBObject();  
  9.       filterDBObject.put("_id"0);  
  10.       filterDBObject.put("cname",1);  
  11.       filterDBObject.put("onumber",1);  
  12.       DBCursordbCursor=mongoTemplate.getCollection(collectionName).find(queryObject,filterDBObject);  
  13.       //排序
  14.       DBObjectsortDBObject=newBasicDBObject();  
  15.       sortDBObject.put("onumber",1);  
  16.       dbCursor.sort(sortDBObject);  
  17.       //分頁查詢
  18.       dbCursor.skip(page.getSkip()).limit(page.getPageSize());  
  19.       //總數
  20.       int count=dbCursor.count();  
  21.       //迴圈指標
  22.       List<Orders>datas=newArrayList<Orders>();  
  23.       while (dbCursor.hasNext()) {  
  24.         datas.add(morphia.fromDBObject(Orders.class, dbCursor.next()));  
  25.       }  
  26.       page.setRowCount(count);  
  27.       page.setDatas(datas);  
  28.       return page;  
  29. }  

   我們開始執行DAO時,先初始化Morphia,並往裡面新增我們需要轉換的實體類CLASS

      morphia=new Morphia();

      morphia.map(Orders.class);