前言
上一章節,簡單講解了如何集成
Spring-data-jpa
。本章節,我們來看看如何集成NoSQL
的Mongodb
。mongodb
是最早熱門非關系數據庫的之一,使用也比較普遍。最適合來存儲一些非結構數據了,適合對大量或者無固定格式的數據進行存儲,比如:日志、緩存等。
一點知識
以下部分關於Mongodb
介紹,來自網站:https://www.mongodb.com/cn 、純潔的微笑
MongoDB簡介
MongoDB
(來自於英文單詞“Humongous”,中文含義為“龐大”)是可以應用於各種規模的企業、各個行業以及各類應用程序的開源數據庫。作為一個適用於敏捷開發的數據庫,MongoDB
的數據模式可以隨着應用程序的發展而靈活地更新。與此同時,它也為開發人員 提供了傳統數據庫的功能:二級索引,完整的查詢系統以及嚴格一致性等等。 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:pass@ip:port/database
# 集群模式 mongodb://user:pwd@ip1:port1,ip2:port2/database
spring.data.mongodb.uri=mongodb://127.0.0.1:27017/learning
注意,這里填寫格式
- 單機模式:mongodb://name:pwd@ip:port/database
- 集群模式:mongodb://name:pwd@ip1: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/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
,訪問具體的方法,就可以看見相關結果了。
也可直接利用可視化工具,直接查看數據信息
參考資料
-
https://docs.spring.io/spring-data/mongodb/docs/1.10.14.RELEASE/reference/html
-
https://docs.spring.io/spring-boot/docs/1.5.15.RELEASE/reference/htmlsingle/#boot-features-mongodb
-
http://www.ityouknow.com/springboot/2017/05/08/springboot-mongodb.html
總結
本章節主要介紹了
Mongodb
的集成和簡單的使用。相關更加詳細的用法,可取官網查閱下,若使用MongoRepository
模式,基本和上章節講的Spring-data-jpa
用法差不多,有些細微差別,就是自定義查詢sql上了,畢竟一個是關系型數據庫,一個是NoSql
數據庫,查詢的語法還有略有不同的。而使用MongoRepository
還是MongoTemplate
,就看個人喜好了。自從接觸了jpa
后,是傾向於前者的,畢竟真的比較簡單呀!想多復雜用法的大家自定查閱官網信息吧。
最后
目前互聯網上很多大佬都有
SpringBoot
系列教程,如有雷同,請多多包涵了。原創不易,碼字不易,還希望大家多多支持。若文中有所錯誤之處,還望提出,謝謝。
老生常談
- 個人QQ:
499452441
- 微信公眾號:
lqdevOps
個人博客:http://blog.lqdev.cn
完整示例:https://github.com/xie19900123/spring-boot-learning/tree/master/chapter-31
原文地址:http://blog.lqdev.cn/2018/11/01/springboot/chapter-thirty-one/