Spring Boot學習筆記(三)Repository的使用

Repository的概念

在Spring中有Repository的概念,repository原意指的是倉庫,即數據倉庫的意思。Repository居於業務層和數據層之間,將二者隔離開來,在它的內部封裝了數據查詢和存儲的邏輯。這樣設計的好處有兩個:數據庫

  1. 下降層級之間的耦合:更換、升級ORM引擎(Hibernate)並不會影響業務邏輯
  2. 提升測試效率:若是在測試時能用Mock數據對象代替實際的數據庫操做,運行速度會快不少

Repository和DAO的區別

DAO是傳統MVC中Model的關鍵角色,全稱是Data Access Object。DAO直接負責數據庫的存取工做,乍一看二者很是相似,但從架構設計上講二者有着本質的區別:數組

Repository蘊含着真正的OO概念,即一個數據倉庫角色,負責全部對象的持久化管理。DAO則沒有擺脫數據的影子,仍然停留在數據操做的層面上。Repository是相對對象而言,DAO則是相對數據庫而言,雖然多是同一個東西 ,但側重點徹底不一樣。架構

三種Repository介紹

在Spring和Spring Data JPA中,有三種Repository接口方便開發者直接操做數據倉庫。
它們之間的關係以下:app

圖片描述

CrudRepository

<S extends T> S save(S entity);
  <S extends T> Iterable<S> save(Iterable<S> entities);
  T findOne(ID id);
  boolean exists(ID id);
  Iterable<T> findAll();
  Iterable<T> findAll(Iterable<ID> ids);
  long count();
  void delete(ID id);
  void delete(T entity);
  void delete(Iterable<? extends T> entities);
  void deleteAll();

CrudRepository類如其名,能夠勝任最基本的CRUD操做。其中save方法在可兩用,參數中不存在主鍵時執行insert操做,存在主鍵則執行update操做,至關因而一個upsert操做。ide

PagingAndSortingRepository

Iterable<T> findAll(Sort sort);
  Page<T> findAll(Pageable pageable);

PagingAndSortingRepository繼承了CrudRepository接口,增長了分頁和排序的方法。測試

分頁spa

要達到分頁的目的,須要傳入一個Pageble接口對象,controller中代碼以下:架構設計

@GetMapping("")
public ResponseEntity<?> getList(
  @RequestParam(value="page", defaultValue="0") int page,
  @RequestParam(value="size", defaultValue="10") int size ) {
        
  Pageable pageable = new PageRequest(page, size);
  return new ResponseEntity<Object>(userService.getUserList(pageable), HttpStatus.OK);
}

<說明>設計

  1. @RequestParam註解,代表了須要傳入URL參數page和size,用於計算分頁的offset值。
  2. PageRequest是Pageable的實現類,傳入初始化page和size便可生成分頁參數。

在Service中,僅需加入pageable對象便可達到分頁的效果。代碼以下:code

public Iterable<User> getUserList(Pageable pageable) {
  return userRepo.findAll(pageable);
}

此時在POSTMAN中輸入訪問地址:'127.0.0.1:8080/user?page=0&size=5',獲得如下結果:

{
  "content": [
    { "id": 12, "name": "F1" },
    { "id": 13, "name": "A" },
    { "id": 14, "name": "B" },
    { "id": 15, "name": "C" },
    { "id": 16, "name": "D" }
  ],
  "last": false,
  "totalPages": 3,
  "totalElements": 11,
  "size": 5,
  "number": 0,
  "numberOfElements": 5,
  "first": true,
  "sort": null
}

從結果能夠看出,不只在content中有查詢的數組信息,還包括totalPages等分頁信息。

排序

與分頁相似,要達到排序的目錄,僅須要傳入Sort對象便可,controller中代碼以下:

@GetMapping("")
public ResponseEntity<?> getList(
  @RequestParam(value="page", defaultValue="0") int page,
  @RequestParam(value="size", defaultValue="10") int size ) {
        
  Sort sort = new Sort(Sort.Direction.DESC, "name");
// Pageable pageable = new PageRequest(page, size);
  return new ResponseEntity<Object>(userService.getUserList(sort), HttpStatus.OK);
}

一樣的,在Service中須要新增接口,以下:

public Iterable<User> getUserList(Sort sort) {
  return userRepo.findAll(sort);
}

此時在POSTMAN中輸入訪問地址:'127.0.0.1:8080/user',獲得如下結果:

[
    { "id": 22, "name": "K" },
    { "id": 21, "name": "J" },
    { "id": 20, "name": "I" },
    { "id": 19, "name": "H" },
    { "id": 18, "name": "G" },
    { "id": 12, "name": "F1" },
    { "id": 17, "name": "E" },
    { "id": 16, "name": "D" },
    { "id": 15, "name": "C" },
    { "id": 14, "name": "B" },
    { "id": 13, "name": "A" }
]

獲得的正是name屬性按DESC排序的結果列表

排序後分頁

PagingAndSortingRepository提供了分頁和排序的接口,那若是二者都要作,該怎麼寫呢?
其實在Pageable中,還能夠傳入Sort屬性,這樣就能夠在分頁中達到排序的目的。

一樣的,把Controller代碼稍稍調整一下:

@GetMapping("")
public ResponseEntity<?> getList(
  @RequestParam(value="page", defaultValue="0") int page,
  @RequestParam(value="size", defaultValue="10") int size ) {
        
  Sort sort = new Sort(Sort.Direction.DESC, "name");
  Pageable pageable = new PageRequest(page, size, sort);
  return new ResponseEntity<Object>(userService.getUserList(pageable), HttpStatus.OK);
}

<說明>

  1. Sort對象做爲PageRequest的第三個參數傳入。

這樣調整之後,UserService這邊就不在須要入參爲Sort的getUserList接口了。

此時在POSTMAN中輸入訪問地址:'127.0.0.1:8080/user?page=0&size=5',獲得如下結果:

{
  "content":[
    {"id":22,"name":"K"},
    {"id":21,"name":"J"},
    {"id":20,"name":"I"},
    {"id":19,"name":"H"},
    {"id":18,"name":"G"}
  ],
  "totalPages":3,
  "totalElements":11,
  "last":false,"size":5,
  "number":0,
  "first":true,
  "numberOfElements":5,
  "sort":[{
    "direction":"DESC",
    "property":"name",
    "ignoreCase":false,
    "nullHandling":"NATIVE",
    "ascending":false,
    "descending":true
  }]
}

sort顯然不該該出如今應答結果中,之後的代碼會將它去除出去。

JpaRepository

List<T> findAll();
  List<T> findAll(Sort sort);
  List<T> findAll(Iterable<ID> ids);
  <S extends T> List<S> save(Iterable<S> entities);
  void flush();
  <S extends T> S saveAndFlush(S entity);
  void deleteInBatch(Iterable<T> entities);
  void deleteAllInBatch();
  T getOne(ID id);
  @Override
  <S extends T> List<S> findAll(Example<S> example);
  @Override
  <S extends T> List<S> findAll(Example<S> example, Sort sort);

JpaRepository則進一步在PagingAndSorting的基礎上,擴展了部分功能:

  1. 查詢列表(返回值爲List)
  2. 批量刪除
  3. 強制同步
  4. Example查詢

這部分將在之後的內容中不斷細化。

相關文章
相關標籤/搜索