Spring Boot MongoDB 資料庫應用技巧
一、關於 MongoDB
MongoDB 目前非常流行,在最近的 DB-Engine 排名中居第5位,僅次於傳統的關係型資料庫如 Oracle、Mysql。
然而在非關係型資料庫領域,MongoDB已經持續成為佼佼者一段時間了,這與 MongoDB的一些優勢存在一定關係:
-
無模式(Schema),便於快速開發;
-
面向文件化的資料,基於BSON格式(類JSON),靈活性強
-
高效能,得益於其記憶體計算能力;
-
副本集、自動分片特性,提供了高可用及水平擴充套件能力
MongoDB 的主要物件包括資料庫(database)、集合(collection)、文件物件(document),與關係型資料庫的對應關係如下:
MySql | MongoDB |
---|---|
schema | database |
table | collection |
record | document |
column | field |
與關係型資料庫一樣,MongoDB也支援索引(不支援外來鍵),然而其沒有定義固定的列(Column),欄位可以是任何型別的值,比如數值、陣列或巢狀文件等。 在最近釋出的4.0版本中,MongoDB開始支援事務。可見,在未來這些資料庫之間的差異只會越來越少。
二、Spring-Data-Mongo
Spring-Data-Mongo 是Spring框架對於MongoDB 資料讀寫的ORM 封裝, 與 大家熟悉的 JPA一樣,其在MongoDB-Java-Driver基礎之上做了一些封裝,令應用開發更加簡便。
如下是 SpringData 整體框架的一個概要:
從上圖中可以看出,SpringData 是基於分層設計的。從下之上,分別是:
-
資料庫層;
-
驅動層(JDBC/Driver);
-
ORM層(Repository);
三、整合 MongoDB CRUD
接下來的篇幅,主要針對如何在專案中使用框架進行MongoDB資料庫的讀寫,部分程式碼可供參考。
A. 引入框架
其中 spring-boot-starter-mongodb 是一個膠水元件,宣告對它的依賴會令專案自動引入 spring-data-mongo 、 mongodb-java-driver 等基礎元件。
B. 資料庫配置
我們在 application.properties 中宣告一段配置:
不難理解,這裡是資料庫主機、埠、使用者密碼、資料庫的設定。
C. 資料模型
接下來,要定義資料集合(collection) 的一個結構,以 Book 實體為例:
這裡,我們給Book 實體定義了一些屬性:
屬性名 | 描述 |
---|---|
id | 書籍ID |
author | 作者 |
category | 書籍分類 |
title | 書籍標題 |
voteCount | 投票數量 |
price | 價格 |
publishDate | 釋出日期 |
updateTime | 更新時間 |
createTime | 建立時間 |
除此以外,我們還會用到幾個註解:
註解 | 描述 |
---|---|
@Document | 宣告實體為MongoDB文件 |
@Id | 標記ID屬性 |
@Indexed | 單鍵索引 |
@CompoundIndexes | 複合索引集 |
@CompoundIndex | 複合索引 |
關於MongoDB索引形態,可以參考 官方文件 做一個詳細瞭解。
D. 資料操作
ORM 框架可以讓你通過操作物件來直接影響資料,這樣一來,可以大大減少上手的難度,你不再需要熟悉大量驅動層的API了。
Spring-Data-Mongo 實現了類JPA的介面,通過預定義好的Repository可實現 程式碼方法到資料庫操作語句DML 的對映。
下面是一些例子:
-
BookRepository
我們所看到的 findByAttribute 將會直接被轉換成對應的條件查詢,
如 findByAuthor 等價於
接下來,我們可以方便的在業務邏輯層(service層) 對Repository 進行呼叫,如下:
關於Repository 對映規則,可以從 這裡 找到詳細介紹。
E. 自定義操作
有時候,Repository的方法對映無法較好的滿足一些特定場景,比如高階檢索、區域性更新、覆蓋索引查詢等等, 此時可以使用框架提供的 MongoTemplate 工具類來完成這些定製。
MongoTemplate 提供了大量的 Criteria API 來封裝 Mongo-Java-Driver的實現。
我們一方面可以選擇直接使用該API,另一方面,則可以更加 "優雅" 的整合到Repository 介面,如下面的程式碼:
-
宣告 Custom 介面
-
宣告介面繼承關係
-
實現類
利用 AOP的魔法 ,Spring 框架會自動將我們這段程式碼實現 織入 到Bean物件中, 這樣一來,我們原先對Repository的依賴引用方式就不需要改變了。
四、高階技巧
SpringBoot中完成Mongodb的自動化配置,是通過 MongoAutoConfiguration、MongoDataAutoConfiguration 完成的。
其中MongoAutoConfiguration的實現如下:
從上面的程式碼可見,如果應用程式碼中未宣告 MongoClient、MongoDbFactory,那麼框架會根據配置檔案自動做客戶端的初始化。
通過宣告,可以取消這些自動化配置:
真實線上的專案中,會對MongoDB 客戶端做一些定製 ,下面介紹幾個常見用法
1. 連線池配置
這裡我們所關心的,往往是連線池大小、超時引數閾值、佇列這幾個,
如下:
2. 去掉_class屬性
通過 SpringDataMongo 定義的實體,會自動寫入一個 _class 屬性,大多數情況下這個不是必須的,可以通過配置去掉:
public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MongoMappingContext context) {
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, converter);
return mongoTemplate;
3. 自定義序列化
一些基礎的欄位型別,如 int 、long、string,通過JDK 裝箱類就可以完成, 對於內嵌的物件型別,SpringDataMongo框架會將其轉換為 DBObject物件(java driver 實體)。
一般情況下這已經足夠了,但某些場景下你不得不實現自己的序列化方式,比如通過文件儲存某些特殊格式的內容。
這需要用到 Converter 介面,如下面的程式碼:
4. 讀寫分離
MongoDB 本身支援讀寫分離的實現,前提是採用副本集、分片副本集的架構, 通過宣告客戶端的 ReadPreference 級別可以達到優先讀主、優先讀備的控制。
上面的程式碼中,將會為MongoClient 設定 secondaryPreferred 的讀級別。 ReadPreference 級別包括以下幾種:
級別 | 描述 |
---|---|
primary | 預設值,只從主節點讀,主節點不可用時報錯 |
primaryPreferred | 優先主節點(primary)讀,主節點不可用時到從節點(secondary)讀 |
secondary | 僅從備節點(secondary)讀取資料 |
secondaryPreferred | 優先從備節點讀,從節點不可用時到主節點讀取 |
nearest | 到網路延遲最低的節點讀取資料,不管是主節點還是從節點 |
小結
MongoDB 是當下 NoSQL 資料庫的首選,也有不少服務化架構採用了 MongoDB作為主要資料庫, 其在 4.x版本中即將推出事務功能,在未來該文件資料庫相對於RDBMS的差距將會大大縮小。 也正由於MongoDB 具備 簡單、易擴充套件、高效能等特性,其社群活躍度非常高,是非常值得關注和學習的。
歡迎繼續關注"美碼師的補習系列-springboot篇" ,期待更多精彩內容^-^