To-Do Calendar - Day13 實作查詢列表功能(上)- 用 MongoTemplate 操作 MongoDB

這篇要來實作查詢列表功能,以原子習慣為例,從設計 Document 的資料結構開始,再來實作 Spring Boot 程式。

設計資料結構

對應前端原子習慣畫面與示意的假資料,規劃需要的欄位對照如下:

image

原子習慣列表與原子習慣追蹤

image

原子習慣詳細資料

habits(多對一Document)

  • id(String):文件主鍵
  • userId(String):所屬的使用者id
  • habitList(Array):habit物件陣列
  • createdTime(Timestamp):建立時間
  • lastModifiedTime(Timestamp):最後修改時間

habitTracker(一對一Document)

  • id(String):文件主鍵
  • habitId(String):所屬的原子習慣id
  • year(String):年份
  • pickedDays(Array):達成日期物件陣列
  • createdTime(Timestamp):建立時間
  • lastModifiedTime(Timestamp):最後修改時間

habit(Object)

  • habitId(String):原子習慣id
  • name(String):原子習慣名稱
  • checkColor(String):圈選日期顏色
  • createdTime(Timestamp):建立時間
  • lastModifiedTime(Timestamp):最後修改時間

建立測試資料

向 Collection 新增 Document

  • 語法:db.<集合名稱>.insert(<Document>) 或 db.<集合名稱>.save(<Document>) →新版本已棄用
  • 單筆語法:db.<集合名稱>.insertOne( <document>, { writeConcern: <document> } )
  • 多筆語法:db.<集合名稱>.insertMany( [ <document 1> , <document 2>, … ], { writeConcern: <document>, ordered: <boolean> } )

參數說明

  • document:要寫入的文檔
  • writeConcern:寫入策略,默認為1,即要求確認寫操作,0 是不要求
  • ordered:指定是否按順序寫入,默認true,按順序寫入
    db.habits.insertOne({
      userId: "user01",
      habitList: [
        {
            habitId:"habit01",
            name:"吃早餐",
            checkColor:"red",
            createdTime:1653405213436,
            lastModifiedTime:1653405213436
        },
        {
            id:"habit02",
            name:"喝水2000cc",
            checkColor:"yellow",
            createdTime:1653405213436,
            lastModifiedTime:1653405213436
        },
        {
            id:"habit03",
            name:"寫技術部落格",
            checkColor:"green",
            createdTime:1653405213436,
            lastModifiedTime:1653405213436
        },
      ],
      createdTime: 1653405213436,
      lastModifiedTime: 1653405213436
    })
    
    db.habitTrackers.insertMany([
        {
            habitId:"habit01",
            year:"2022",
            pickedDays:[{ "id": "2022-01-06", "date": "2022-01-05T16:00:00.000Z" }],
            createdTime:1653405213436,
            lastModifiedTime:1653405213436
        },
        {
            habitId:"habit02",
            year:"2022",
            pickedDays:[{ "id": "2022-02-06", "date": "2022-02-05T16:00:00.000Z" }],
            createdTime:1653405213436,
            lastModifiedTime:1653405213436
        },
        {
            habitId:"habit03",
            year:"2022",
            pickedDays:[{ "id": "2022-03-06", "date": "2022-03-05T16:00:00.000Z" }],
            createdTime:1653405213436,
            lastModifiedTime:1653405213436
        }
    ])
    
  • 在 IntelliJ MongoDB console 運行上述語法後,查詢結果如下,測試資料建立完成後,接下來就可以開始進入 Spring Boot 程式。

實作原子習慣查詢列表功能

第一步:設定 Spring Boot 專案的資料庫連線

  • pom.xml 因之前有勾選匯入 MongoDB 函式庫,所以可以跳過
  • 在 application.properties 添加 MongoDB 資料庫的連線資訊
    spring.data.mongodb.uri=mongodb://localhost:27017/todoCalendar
    

設定好後,這個 Spring Boot 專案就可以去存取 localMongoDB 資料庫的數據了!

使用 Controller-Service-Dao 的三層式架構

在 src/main/java/com.fiber.todocalendar package 底下建立 Controller、Service、Dao package

  • Controller 層:負責接收 Http request,並且驗證請求參數
  • Service 層:負責商業邏輯的處理
  • Dao 層:負責和資料庫溝通
    image

第二步:建立 Document 所對應的 Entity

  • 先建一個 model package
  • 接著在 model package 底下建立 Habits class、HabitTrackers class、Habit class
  • 在 Habit class 加上 @Data,和資料庫中 habitTrackers Document 所對應的變數
  • 在 HabitTrackers class 和 Habits class 加上 @Data@Document 註解,並在 @Document 註解括號中指定 collection 名稱
  • 實作和資料庫中所對應的變數,並在 id 屬性上加上 @Id 註解
    image

    Habits class

    image

    HabitTracker class

    image

    Habit class

實作 Dao 層(使用 MongoTemplate)

  • 在 dao package 底下建立 HabitsDao interface
  • 在 dao package 底下建立 impl package,在 impl package 底下再建立 HabitsDaoImpl class
  • 為讓 HabitsDaoImpl class 成為 Bean,在 HabitsDaoImpl class 上加上 @component 註解,並implements HabitsDao interface,然後使用 @Autowired 註解注入 MongoTemplate
  • 回到 HabitsDao interface,宣告一個 getHabitsByUserId 方法,返回類型為 Habits
  • 接著再到 HabitsDaoImpl class,實作 getHabitsByUserId 方法
    image

    HabitrsDao interface

    image

    HabitsDaoImpl class


實作 Service 層

  • 在 service package 底下建立 HabitsService interface
  • 在 service package 底下建立 impl package
  • 在 impl package 底下建立 HabitsServiceImpl class
  • 為讓 HabitsServiceImpl class 成為 Bean,在 HabitsDaoImpl class 上加上 @component 註解,並 implements HabitsService interface,然後使用 @Autowired 註解注入 HabitsDao
  • 回到 HabitTrackersService interface,宣告一個 getHabitTrackersByUserId 方法,返回類型為 Habits
  • 接著再到 HabitsServiceImpl class,實作 getHabitsByUserId 方法(call habitTrackerDao 的 getHabitsByUserId 方法)
    image

    HabitsService interface

    image

    HabitsServiceImpl class


實作 Controller 層

  • 在 controller package 底下建立 HabitsController class
  • 在 HabitsController class 上加上 @RestController 註解,並使用 @Autowired 註解注入 HabitsService
  • 新增 getHabitsByUserId 方法,返回類型為 ResponseEntity<Habits>
  • 根據 RESTful 的設計原則,查詢所對應的是 GET 方法,所以在方法上加上 @GetMapping 註解,表示前端要使用 GET 方法來請求 API
  • @GetMapping 註解括號中指定 url 路徑,並使用 @PathVariable 註解去取得 url 路徑的值
  • 接著實作 getHabitsByUserId 方法(call HabitsService 的 getHabitsByUserId 方法)
    image

    habitsController class

  • 接著運行 Spring Boot 程式,使用 API Tester 測試一下效果
    image

到這邊就已經完成查詢原子習慣列表功能的實作了(後端的部分)~

延伸閱讀

參考資料

comments

comments powered by Disqus