SpringBoot | 第三十一章:MongoDB的整合和使用
前言
上一章節,簡單講解了如何整合
Spring-data-jpa
。本章節,我們來看看如何整合NoSQL
的Mongodb
。mongodb
是最早熱門非關係資料庫的之一,使用也比較普遍。最適合來儲存一些非結構資料了,適合對大量或者無固定格式的資料進行儲存,比如:日誌、快取等。
一點知識
以下部分關於Mongodb
介紹,來自網站:https://www.mongodb.com/cn 、純潔的微笑
MongoDB簡介
MongoDB
(來自於英文單詞“Humongous”,中文含義為“龐大”)是可以應用於各種規模的企業、各個行業以及各類應用程式的開源資料庫。作為一個適用於敏捷開發的資料庫,MongoDB
的資料模式可以隨著應用程式的發展而靈活地更新。與此同時,它也為開發人員 提供了傳統資料庫的功能:二級索引,完整的查詢系統以及嚴格一致性等等。 MongoDB
MongoDB
是專為可擴充套件性,高效能和高可用性而設計的資料庫。它可以從單伺服器部署擴充套件到大型、複雜的多資料中心架構。利用記憶體計算的優勢,MongoDB
能夠提供高效能的資料讀寫操作。 MongoDB
的本地複製和自動故障轉移功能使您的應用程式具有企業級的可靠性和操作靈活性。
簡單來說,MongoDB
是一個基於分散式檔案儲存的資料庫,它是一個介於關係資料庫和非關係資料庫之間的產品,其主要目標是在鍵/值儲存方式(提供了高效能和高度伸縮性)和傳統的RDBMS系統(具有豐富的功能)之間架起一座橋樑,它集兩者的優勢於一身。
MongoDB
支援的資料結構非常鬆散,是類似json
的bson格式,因此可以儲存比較複雜的資料型別,也因為他的儲存格式也使得它所儲存的資料在Nodejs程式應用中使用非常流暢。
傳統的關係資料庫一般由資料庫(database)、表(table)、記錄(record)三個層次概念組成,MongoDB是由資料庫(database)、集合(collection)、文件物件(document)三個層次組成。MongoDB對於關係型資料庫裡的表,但是集合中沒有列、行和關係概念,這體現了模式自由的特點。
MongoDB
中的一條記錄就是一個文件,是一個數據結構,由欄位和值對組成。MongoDB文件與JSON物件類似。欄位的值有可能包括其它文件、陣列以及文件陣列。MongoDB支援OS X、Linux及Windows等作業系統,並提供了Python,PHP,Ruby,Java及C++語言的驅動程式,社群中也提供了對Erlang及.NET等平臺的驅動程式。
MongoDB的適合對大量或者無固定格式的資料進行儲存,比如:日誌、快取等。對事物支援較弱,不適用複雜的多文件(多表)的級聯查詢。
SpringBoot整合MongoDB
得力於
SpringBoot
方便性,整合MongoDB
也是很簡單的。可通過三種方式進行訪問,分別是:原生Db物件
、MongoTemplate
以及MongoRepository
。原生的方式需要連線其語法規則,這裡就不闡述了,畢竟不熟悉。還是使用封裝好的吧,開箱急用!
準備工作
本文示例的MongoDB版本為:4.0.3。 視覺化工具為:studio-3t-x64。
至於MongoDB
如何安裝,大家簡單百度下就好了,很簡單。下載個msi
,直接安裝即可。
下載地址:https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-4.0.3-signed.msi
0.加入POM依賴。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
1.建立實體。
/**
* 通知訊息物件
* @author oKong
*
*/
@Document(collection="notify_msg")//集合名
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class NotifyMsg implements Serializable{
/**
*
*/
private static final long serialVersionUID = -8985545025018238754L;
@Id
String id;
/**
* 訊息型別
*/
@Indexed
String notifyType;
/**
* 訊息單號
*/
@Indexed
String notifyNo;
/**
* 訊息通知日期
*/
String notifyDate;
/**
* 訊息體
*/
@Field("notifyMsg")//可指定儲存時的欄位名
String notifyMsg;
/**
* 建立時間
*/
@CreatedDate
Date gmtCreate;
}
這裡注意:@Document(collection="notify_msg") 表示:操作的集合為:notify_msg
。
這個可手動使用工具建立下。
另外,針對@CreatedDate
註解,也和之前的jpa
用法一直,建立時會自動賦值,需要在啟動類中新增@EnableMongoAuditing
註解使其生效!
同時,可使用@Field
註解,可指定儲存的鍵值名稱,預設就是類欄位名。如設定@Field("notify_Msg")
後,效果如下:
2.配置檔案中填寫連線地址。
#mongodb
# 單機模式 mongodb://name:[email protected]:port/database
# 叢集模式 mongodb://user:[email protected]:port1,ip2:port2/database
spring.data.mongodb.uri=mongodb://127.0.0.1:27017/learning
注意,這裡填寫格式
- 單機模式:mongodb://name:[email protected]:port/database
- 叢集模式:mongodb://name:[email protected]:port1,ip2:port2/database
3.啟動類編寫。
/**
* mongodb 整合示例
* @author oKong
*
*/
@SpringBootApplication
@EnableMongoAuditing
//@EnableMongoRepositories(basePackages="cn.lqdev")//當有些dao不在default page下時 可通過此方法進行註冊掃描包
@Slf4j
public class MongodbApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(MongodbApplication.class, args);
log.info("spring-boot-mongodb-chapter31啟動!");
}
}
注意:當使用MongoRepositories
時,可能有些MongoRepositories
類不在預設的包路徑(啟動類路徑)下,可使用@EnableMongoRepositories
的basePackages
需要掃描的路徑資訊。若都在預設的包路徑下,可以不加此註解的。
MongoTemplate方式
以下示例下
MongoTemplate
方式進行資料操作。
0.建立一個介面類:
/**
* 介面服務
* @author oKong
*
*/
public interface NotifyMsgService {
/**
* 儲存資料
* @author 作者:oKong
*/
NotifyMsg saveNotifyMsg(NotifyMsg msg);
/**
* 根據訊息號查詢
* @author 作者:oKong
*/
NotifyMsg findNotifyMsgByNo(String notifyNo);
/**
* 根據訊息日期查詢
* @author 作者:oKong
*/
List<NotifyMsg> findNotifyMsgByDate(String notifyDate);
/**
* 根據id進行刪除 返回刪除的物件
* @author 作者:oKong
*/
NotifyMsg delNotifyMsgById(String id);
}
1.介面實現類,引入MongoTemplate
。
/**
* MongoTemplate 訪問實現
* @author oKong
*
*/
@Service
public class NotifyMsgServiceImpl implements NotifyMsgService{
@Autowired
MongoTemplate mongoTemplate;
@Override
public NotifyMsg saveNotifyMsg(NotifyMsg msg) {
//使用 save和insert都可以進行插入
//區別:當存在"_id"時
//insert 插入已經存在的id時 會異常
//save 則會進行更新
//簡單來說 save 就是不存在插入 存在更新
mongoTemplate.insert(msg);
mongoTemplate.save(msg);
return msg;
}
@Override
public NotifyMsg findNotifyMsgByNo(String notifyNo) {
//根據Criteria 改造查詢條件
Query query = new Query(Criteria.where("notifyNo").is(notifyNo));
return mongoTemplate.findOne(query, NotifyMsg.class);
}
@Override
public List<NotifyMsg> findNotifyMsgByDate(String notifyDate) {
//查詢 notifyDate 根據Criteria 改造查詢條件
Query query = new Query(Criteria.where("notifyDate").is(notifyDate));
return mongoTemplate.find(query, NotifyMsg.class);
}
@Override
public NotifyMsg delNotifyMsgById(String id) {
//查詢 id 根據Criteria 改造查詢條件
Query query = new Query(Criteria.where("id").is(id));
return mongoTemplate.findAndRemove(query, NotifyMsg.class);
}
}
針對查詢,可以使用org.springframework.data.mongodb.core.query.Criteria
物件進行構造查詢條件。其提供的方法如下:
具體使用時,可根據實際情況進行組合查詢條件。
針對save
和insert
也需要注意下:
- 在無
_id
情況下,兩者都能進行新增操作。 - 存在
_id
,同時記錄庫裡不存在,兩者都是進行插入操作。 - 存在
_id
,同時庫裡也存在記錄,save
相當於進行更新操作。而insert
直接就異常了。
2.建立示例控制層。
/**
* mongoTemplate 示例
* @author oKong
*
*/
@RestController
@RequestMapping("/template")
@Slf4j
public class MongoTemplateController {
@Autowired
NotifyMsgService notifyMsgService;
@PostMapping("/add")
public NotifyMsg add(NotifyMsg msg) {
log.info("mongoTemplate方式新增:{}", msg);
return notifyMsgService.saveNotifyMsg(msg);
}
@PostMapping("del/{id}")
public NotifyMsg del(@PathVariable String id) {
log.info("mongoTemplate方式刪除:{}", id);
return notifyMsgService.delNotifyMsgById(id);
}
@GetMapping("/find/{no}")
public NotifyMsg findNotifyMsgByNo(@PathVariable String no){
log.info("mongoTemplate方式查詢:notifyNo-{}", no);
return notifyMsgService.findNotifyMsgByNo(no);
}
@GetMapping("/find/list/{date}")
public List<NotifyMsg> findNotifyMsgByDate(@PathVariable String date){
log.info("mongoTemplate方式查詢:notifyDate-{}", date);
return notifyMsgService.findNotifyMsgByDate(date);
}
}
3.啟動應用,使用Postman
進行訪問。
- 新增:http://127.0.0.1:8080//template/add
可以看見,已經返回對應的資訊,同時資料庫也可看見記錄了。
其他的都是類似的,大家可自行訪問下:
- 根據日期返回列表資訊:http://127.0.0.1:8080//template/find/list/具體日期
- 根據ID刪除:http://127.0.0.1:8080/template/del/具體ID值
- 根據訊息號查詢:http://127.0.0.1:8080//template/find/具體訊息號
MongoRepository方式
以上還需要自己編寫一些類啥的,現在是
jpa
的方式進行操作資料,優雅,簡單。
0.建立資源類
/**
* MongoRepository 示例
* @author oKong
*
*/
public interface NotifyMsgDao extends MongoRepository<NotifyMsg, String>{
/*
* 根據訊息號進行查詢
*/
NotifyMsg findByNotifyNo(String notifyNo);
/**
* 根據日期查詢 自定義查詢
* @author 作者:oKong
*/
//需要注意 查詢的語法結構 ,同時這裡和`jpa`不一樣的地方是,第一個索引值從0 開始。。
@Query("{'notifyDate':?0}")
Page<NotifyMsg> queryBySql(String notifyDate,Pageable pageable);
}
這裡需要注意一個地方:和上一章節的自定義sql不同之處是,引數索引值從0
開始。
同時,要注意查詢的語法。具體用法,可檢視:https://docs.spring.io/spring-data/mongodb/docs/1.10.14.RELEASE/reference/html/#mongodb.repositories.queries 這裡簡單截圖下:
1.編寫示例控制層。
/**
* MongoRepository 示例
* @author oKong
*
*/
@RestController
@RequestMapping("/repository")
@Slf4j
public class MongoRepositoryController {
@Autowired
NotifyMsgDao notifyMsgDao;
@PostMapping("/add")
public NotifyMsg add(NotifyMsg msg) {
log.info("repository方式新增:{}", msg);
return notifyMsgDao.save(msg);
}
@GetMapping("/find/sql/{date}")
public Page<NotifyMsg> queryBySql(@PathVariable String date){
Pageable pageable = new PageRequest(0, 10);
log.info("repository方式分頁sql查詢日期:{}", date);
return notifyMsgDao.queryBySql(date, pageable);
}
@GetMapping("/find/{no}")
public NotifyMsg findByNotifyNo(@PathVariable String no) {
log.info("repository方式查詢單號:{}", no);
return notifyMsgDao.findByNotifyNo(no);
}
}
2.啟動應用,使用Postman
,訪問具體的方法,就可以看見相關結果了。
- 新增:http://127.0.0.1:8080/repository/add
- 根據訊息日期查詢:http://127.0.0.1:8080/repository/find/sql/具體日期
- 根據訊息號查詢:http://127.0.0.1:8080//template/find/具體訊息號
也可直接利用視覺化工具,直接檢視資料資訊
參考資料
總結
本章節主要介紹了
Mongodb
的整合和簡單的使用。相關更加詳細的用法,可取官網查閱下,若使用MongoRepository
模式,基本和上章節講的Spring-data-jpa
用法差不多,有些細微差別,就是自定義查詢sql上了,畢竟一個是關係型資料庫,一個是NoSql
資料庫,查詢的語法還有略有不同的。而使用MongoRepository
還是MongoTemplate
,就看個人喜好了。自從接觸了jpa
後,是傾向於前者的,畢竟真的比較簡單呀!想多複雜用法的大家自定查閱官網資訊吧。
最後
目前網際網路上很多大佬都有
SpringBoot
系列教程,如有雷同,請多多包涵了。原創不易,碼字不易,還希望大家多多支援。若文中有所錯誤之處,還望提出,謝謝。
老生常談
- 個人QQ:
499452441
- 微信公眾號:
lqdevOps