SpringBoot系列(18):SpringBoot整合MongoDB實戰(zhàn)一之新增修改與簡單查詢

作者: 修羅debug
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 by-sa 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。


摘要:MongoDB,也稱之為文檔型數(shù)據(jù)庫,是目前市面上相當(dāng)流行的其中一種NoSQL數(shù)據(jù)庫,也是眾多NoSQL數(shù)據(jù)庫中最接近于“關(guān)系型數(shù)據(jù)庫”的非關(guān)系型數(shù)據(jù)庫,可以實現(xiàn)對象實體信息以“Document文檔”的形式進(jìn)行存儲。我們花2篇文章分享介紹如何基于Spring Boot2.0搭建的項目整合MongoDB中間件,實現(xiàn)如何對業(yè)務(wù)模塊進(jìn)行CRUD與分頁查詢。

內(nèi)容:文檔型數(shù)據(jù)庫MongoDB是眾多NoSQL數(shù)據(jù)庫的一種,在如今的企業(yè)級應(yīng)用系統(tǒng)、特別是大數(shù)據(jù)的應(yīng)用系統(tǒng)中,其普及程度也是越來越高,如下圖所示,為DB-Engine在2019年10月份發(fā)布的數(shù)據(jù)庫的使用排名(只截取部分圖,其余詳細(xì)的大家可以自己去看看):


你會發(fā)現(xiàn),排在前四/五的幾位是目前數(shù)據(jù)庫領(lǐng)域中長期霸占著“老大哥地位”的幾種“關(guān)系型數(shù)據(jù)庫”,即Oracle、MySQL、SQL Server和PostgreSQL,而緊隨其后的則是MongoDB,連Redis都還得跟它隔著2個檔次!在這里,順便給大家交代一下MongoDB的中文技術(shù)社區(qū):http://www.mongoing.com/ 及其中文文檔:http://www.mongoing.com/docs/

事實上,MongoDB在實際的項目開發(fā)中也逐漸得到了普及,特別是在一些需要實現(xiàn)海量數(shù)據(jù)存儲、查詢功能以及高并發(fā)、高可用的業(yè)務(wù)場景,MongoDB更是能發(fā)揮其穩(wěn)定、高效和可靠的性能(據(jù)說單節(jié)點MongoDB可以輕松存取億級容量的數(shù)據(jù))!

因此,我們覺得是時候擼一波MongoDB在企業(yè)級應(yīng)用項目中的代碼實戰(zhàn)了。工欲善其事,必先利其器,在開擼之前,我們需要在本地或者云服務(wù)器安裝好MongoDB服務(wù),當(dāng)然啦,Debug建議最好也同時在本地安裝一個“MongoDB可視化管理工具”,在這里我推薦Robo 3T,如下圖所示:


其安裝過程,在這里Debug就不貼出來了,大伙兒自己要學(xué)會多動手,所謂“自己動手、豐衣足食”便是這個道理!

值得一提的是,文檔型數(shù)據(jù)庫MongoDB,顧名思義,其底層存儲的一條數(shù)據(jù)便是一個“Document”,即文檔,多個文檔便組成了一個“Collection”,即集合,多個集合便組成了一個“DataBase”,即數(shù)據(jù)庫。這樣子聽起來,你會發(fā)現(xiàn)它跟“關(guān)系型數(shù)據(jù)庫”在一些專業(yè)詞匯上有些雷同之處,下面為Debug親自制作的一張MongoDB與關(guān)系型數(shù)據(jù)庫在一些專有詞匯上的聯(lián)系圖(切記:只是含義上的聯(lián)系哈!在底層或者業(yè)務(wù)層面是一丁點關(guān)系都沒有的),這張圖可以方便各位小伙伴理解、記憶MongoDB的相關(guān)專業(yè)詞匯,在后續(xù)代碼實戰(zhàn)中才不會懵逼!


最后一點,需要重點提及的是,MongoDB底層最終存儲的一條一條的Document、一條一條的文檔記錄,而這些文檔記錄的數(shù)據(jù)結(jié)構(gòu)是“Json格式”的,如下圖所示:


好了,說了這么多,是時候進(jìn)入實戰(zhàn)環(huán)節(jié)了,下面我們就以之前搭建的Spring Boot2.0企業(yè)級的項目為奠基,整合MongoDB中間件,然后以“用戶模塊User”為業(yè)務(wù)模塊案例,初步體驗Spring Boot2.0整合MongoDB 實現(xiàn)基本的新增、修改與簡單的查詢。

(1)首先,自然是需要貼出用戶模塊User對應(yīng)的數(shù)據(jù)庫表user啦,其DDL定義如下所示:

CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '名字',
`code` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '工號',
`email` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '郵箱',
`is_active` int(11) DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶信息表';

緊接著,為了能在我們的企業(yè)級應(yīng)用中使用MongoDB服務(wù),我們需要加入MongoDB中間件相關(guān)的服務(wù)依賴以及服務(wù)配置,在pom.xml中加入依賴,如下所示:  

     <!--mongodb-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

在配置文件application.properties中加入MongoDB服務(wù)的鏈接配置,如下所示:  

#mongodb

#方式一
#spring.data.mongodb.uri=mongodb://localhost:27017/SpringBootMongoDB
#spring.data.mongodb.uri=mongodb://root:root@127.0.0.1:27017/SpringBootMongoDB

#方式二
spring.data.mongodb.database=SpringBootMongoDB
spring.data.mongodb.host=127.0.0.1
spring.data.mongodb.port=27017
#spring.data.mongodb.username=
#spring.data.mongodb.password=

在上面,Debug提供了兩種方式可供大家自行選擇配置。而我們會在后續(xù)接下來的代碼實戰(zhàn)中使用MongoDB服務(wù)提供給開發(fā)者使用的便捷利器:MongoTemplate,這個模板組件便會自動讀取配置文件application.properties中的相關(guān)信息,從而建立到MongoDB服務(wù)中間件的鏈接。

(2)緊接著,我們創(chuàng)建一個MongoUserRepository服務(wù)類,在其中編寫實現(xiàn)“新增、批量新增、更新、簡單列表查詢和主鍵查詢”的邏輯,如下所示:

/**
* @Author:debug (SteadyJack)
* @Link: weixin-> debug0868 qq-> 1948831260
* @Date: 2019/11/13 11:14
**/
@Component
public class MongoUserRepository{
private static final Logger log= LoggerFactory.getLogger(MongoUserRepository.class);

@Autowired
private MongoTemplate mongoTemplate;

@Autowired
private UserMapper userMapper;

//TODO:新增:先插入數(shù)據(jù),再插入MongoDB(也可以不插入數(shù)據(jù)庫,而直接插入MongoDB)
@Transactional(rollbackFor = Exception.class)
public void save(final MongoUser user) throws Exception{
User entity=new User();
BeanUtils.copyProperties(user,entity, "id");
userMapper.insertSelective(entity);

user.setId(entity.getId());
mongoTemplate.save(user);
}

//TODO:批量新增
public void saveAll(final List<MongoUser> list) throws Exception{
if (list!=null && !list.isEmpty()){
list.forEach(user -> {
log.info("-------mongoDB批量新增---------");

User entity=new User();
BeanUtils.copyProperties(user,entity, "id");
userMapper.insertSelective(entity);

user.setId(entity.getId());
});
mongoTemplate.insertAll(list);
}
}

//TODO:查詢-列表
public List<MongoUser> queryAll() throws Exception{
return mongoTemplate.findAll(MongoUser.class);
}

//TODO:查詢-主鍵查詢
public MongoUser queryById(final Integer id) throws Exception{
return mongoTemplate.findById(id,MongoUser.class);
}

//TODO:查詢-帶條件查詢
public List<MongoUser> queryByName(final String name) throws Exception{
Criteria criteria=Criteria.where("name").is(name);
return mongoTemplate.find(Query.query(criteria),MongoUser.class);
}

//TODO:更新
@Transactional(rollbackFor = Exception.class)
public void update(final MongoUser user) throws Exception{
User entity=new User();
BeanUtils.copyProperties(user,entity);
userMapper.updateByPrimaryKeySelective(entity);

Query query=Query.query(Criteria.where("id").is(user.getId()));
Update update=Update.update("name",user.getName()).set("code",user.getCode()).set("email",user.getEmail());
mongoTemplate.updateFirst(query,update,MongoUser.class);
}
}

上述相應(yīng)方法的代碼邏輯其實也不是很難理解,擼過Spring Data JPA的小伙伴估計對于其中的Query、Criteria啥的會感覺相當(dāng)親切!接下來,我們需要單獨寫一寫每個方法的測試案例!

(1)首先,我們先來插入一個用戶信息,即一條文檔記錄吧,如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = MainApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MongoTest2 {
private static final Logger log= LoggerFactory.getLogger(MongoTest2.class);

@Autowired
private MongoUserRepository mongoUserRepository;

@Test
public void method1() throws Exception{
log.info("---單元測試1---");
List<MongoUser> list=mongoUserRepository.queryAll();
log.info("---查詢所有:{}---",list);

MongoUser mongoUser=new MongoUser(null,"曹操","20010","caocao@qq.com",1);
mongoUserRepository.save(mongoUser);
log.info("-----插入成功-----");

list=mongoUserRepository.queryAll();
log.info("---查詢所有:{}---",list);
}
}

運行該Java單元測試案例,可以得到如下圖的運行結(jié)果:


(2)除此之外,我們可以對其進(jìn)行“批量新增”、“列表查詢與主鍵查詢”和“更新”操作,其剩余的Java單元測試案例代碼如下所示:

    @Test
public void method2() throws Exception{
log.info("---單元測試2---");
List<MongoUser> list= Lists.newLinkedList();
list.add(new MongoUser(null,"宋江","40021","40021@126.com",1));
list.add(new MongoUser(null,"盧俊義","40022","40022@126.com",1));
list.add(new MongoUser(null,"吳用","40023","40023@126.com",1));
list.add(new MongoUser(null,"魯智深","40024","40024@126.com",1));
list.add(new MongoUser(null,"武松","40025","40025@126.com",1));

list.add(new MongoUser(null,"曹操","50001","50001@qq.com",1));
list.add(new MongoUser(null,"劉備","50002","50002@qq.com",1));
list.add(new MongoUser(null,"孫權(quán)","50003","50003@qq.com",1));
list.add(new MongoUser(null,"關(guān)羽","50004","50004@qq.com",1));
list.add(new MongoUser(null,"趙云","50005","50005@qq.com",1));

mongoUserRepository.saveAll(list);
log.info("-----批量插入成功-----");

list=mongoUserRepository.queryAll();
log.info("---查詢所有:{}---",list);
}

@Test
public void method3() throws Exception{
log.info("---單元測試3---");

final Integer id=343686;
MongoUser entity=mongoUserRepository.queryById(id);
log.info("---根據(jù)主鍵id查詢={},結(jié)果={}---",id,entity);

final String name="張飛";
List<MongoUser> list=mongoUserRepository.queryByName(name);
log.info("---根據(jù)姓名查詢,name={},結(jié)果={}---",name,list);
}

@Test
public void method4() throws Exception{
log.info("---單元測試4---");

MongoUser entity=new MongoUser(343686,"李四","30023","lisi@sina.com",1);
mongoUserRepository.update(entity);

entity=mongoUserRepository.queryById(343686);
log.info("---根據(jù)主鍵id查詢,結(jié)果={}---",entity);
}

運行相應(yīng)的測試方法,并觀察控制臺所打印出來的結(jié)果,如果沒啥問題,即可打開Navicat以及Robo 3T查看相應(yīng)的數(shù)據(jù)的狀況,最終你會發(fā)現(xiàn)也是沒啥問題!

對于MongoDB的初步體驗至此我們結(jié)束了,但是MongoDB的強(qiáng)大之處卻不僅僅局限于此,在文章的開始我們就給大家交代過了,MongoDB底層采用的是“列式存儲”、Json格式數(shù)據(jù)結(jié)構(gòu)來存儲數(shù)據(jù)的,特別適用于大數(shù)據(jù)量、海量數(shù)據(jù)的存儲以及查詢。故而在下一篇章,我們將往MongoDB塞入40多萬(當(dāng)然啦,也可以是百萬、千萬甚至是億級別)的數(shù)據(jù),然后再給大家分享一下分頁查詢和刪除的功能。

好了,本篇文章我們就介紹到這里了,其他相關(guān)的技術(shù),感興趣的小伙伴可以關(guān)注底部Debug的技術(shù)公眾號,或者加Debug的微信,拉你進(jìn)“微信版”的真正技術(shù)交流群!一起學(xué)習(xí)、共同成長!

補(bǔ)充:

1、本文涉及到的相關(guān)的源代碼可以到此地址,check出來進(jìn)行查看學(xué)習(xí):

https://gitee.com/steadyjack/SpringBootTechnology

2、最近Debug發(fā)布了幾門重量級的課程,感興趣的小伙伴可以前往觀看學(xué)習(xí):
(1) 緩存中間件Redis技術(shù)入門與應(yīng)用場景實戰(zhàn)(SpringBoot2.x + 搶紅包系統(tǒng)設(shè)計與實戰(zhàn)) 
https://www.fightjava.com/web/index/course/detail/12

(2)  企業(yè)權(quán)限管理平臺(SpringBoot2.0+Shiro+Vue+Mybatis)
https://www.fightjava.com/web/index/course/detail/8

3、關(guān)注一下Debug的技術(shù)微信公眾號,最新的技術(shù)文章、課程以及技術(shù)專欄將會第一時間在公眾號發(fā)布哦!