SpringBoot系列(18):SpringBoot整合MongoDB实战一之新增修改与简单查询

作者: 修罗debug
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。


摘要:MongoDB,也称之为文档型数据库,是目前市面上相当流行的其中一种NoSQL数据库,也是众多NoSQL数据库中最接近于“关系型数据库”的非关系型数据库,可以实现对象实体信息以“Document文档”的形式进行存储。我们花2篇文章分享介绍如何基于Spring Boot2.0搭建的项目整合MongoDB中间件,实现如何对业务模块进行CRUD与分页查询。

内容:文档型数据库MongoDB是众多NoSQL数据库的一种,在如今的企业级应用系统、特别是大数据的应用系统中,其普及程度也是越来越高,如下图所示,为DB-Engine在2019年10月份发布的数据库的使用排名(只截取部分图,其余详细的大家可以自己去看看):


你会发现,排在前四/五的几位是目前数据库领域中长期霸占着“老大哥地位”的几种“关系型数据库”,即Oracle、MySQL、SQL Server和PostgreSQL,而紧随其后的则是MongoDB,连Redis都还得跟它隔着2个档次!在这里,顺便给大家交代一下MongoDB的中文技术社区:http://www.mongoing.com/ 及其中文文档:http://www.mongoing.com/docs/

事实上,MongoDB在实际的项目开发中也逐渐得到了普及,特别是在一些需要实现海量数据存储、查询功能以及高并发、高可用的业务场景,MongoDB更是能发挥其稳定、高效和可靠的性能(据说单节点MongoDB可以轻松存取亿级容量的数据)!

因此,我们觉得是时候撸一波MongoDB在企业级应用项目中的代码实战了。工欲善其事,必先利其器,在开撸之前,我们需要在本地或者云服务器安装好MongoDB服务,当然啦,Debug建议最好也同时在本地安装一个“MongoDB可视化管理工具”,在这里我推荐Robo 3T,如下图所示:


其安装过程,在这里Debug就不贴出来了,大伙儿自己要学会多动手,所谓“自己动手、丰衣足食”便是这个道理!

值得一提的是,文档型数据库MongoDB,顾名思义,其底层存储的一条数据便是一个“Document”,即文档,多个文档便组成了一个“Collection”,即集合,多个集合便组成了一个“DataBase”,即数据库。这样子听起来,你会发现它跟“关系型数据库”在一些专业词汇上有些雷同之处,下面为Debug亲自制作的一张MongoDB与关系型数据库在一些专有词汇上的联系图(切记:只是含义上的联系哈!在底层或者业务层面是一丁点关系都没有的),这张图可以方便各位小伙伴理解、记忆MongoDB的相关专业词汇,在后续代码实战中才不会懵逼!


最后一点,需要重点提及的是,MongoDB底层最终存储的一条一条的Document、一条一条的文档记录,而这些文档记录的数据结构是“Json格式”的,如下图所示:


好了,说了这么多,是时候进入实战环节了,下面我们就以之前搭建的Spring Boot2.0企业级的项目为奠基,整合MongoDB中间件,然后以“用户模块User”为业务模块案例,初步体验Spring Boot2.0整合MongoDB 实现基本的新增、修改与简单的查询。

(1)首先,自然是需要贴出用户模块User对应的数据库表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='用户信息表';

紧接着,为了能在我们的企业级应用中使用MongoDB服务,我们需要加入MongoDB中间件相关的服务依赖以及服务配置,在pom.xml中加入依赖,如下所示:  

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

在配置文件application.properties中加入MongoDB服务的链接配置,如下所示:  

#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提供了两种方式可供大家自行选择配置。而我们会在后续接下来的代码实战中使用MongoDB服务提供给开发者使用的便捷利器:MongoTemplate,这个模板组件便会自动读取配置文件application.properties中的相关信息,从而建立到MongoDB服务中间件的链接。

(2)紧接着,我们创建一个MongoUserRepository服务类,在其中编写实现“新增、批量新增、更新、简单列表查询和主键查询”的逻辑,如下所示:

/**
* @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:新增:先插入数据,再插入MongoDB(也可以不插入数据库,而直接插入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);
}
}

上述相应方法的代码逻辑其实也不是很难理解,撸过Spring Data JPA的小伙伴估计对于其中的Query、Criteria啥的会感觉相当亲切!接下来,我们需要单独写一写每个方法的测试案例!

(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单元测试案例,可以得到如下图的运行结果:


(2)除此之外,我们可以对其进行“批量新增”、“列表查询与主键查询”和“更新”操作,其剩余的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,"孙权","50003","50003@qq.com",1));
list.add(new MongoUser(null,"关羽","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("---根据主键id查询={},结果={}---",id,entity);

final String name="张飞";
List<MongoUser> list=mongoUserRepository.queryByName(name);
log.info("---根据姓名查询,name={},结果={}---",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("---根据主键id查询,结果={}---",entity);
}

运行相应的测试方法,并观察控制台所打印出来的结果,如果没啥问题,即可打开Navicat以及Robo 3T查看相应的数据的状况,最终你会发现也是没啥问题!

对于MongoDB的初步体验至此我们结束了,但是MongoDB的强大之处却不仅仅局限于此,在文章的开始我们就给大家交代过了,MongoDB底层采用的是“列式存储”、Json格式数据结构来存储数据的,特别适用于大数据量、海量数据的存储以及查询。故而在下一篇章,我们将往MongoDB塞入40多万(当然啦,也可以是百万、千万甚至是亿级别)的数据,然后再给大家分享一下分页查询和删除的功能。

好了,本篇文章我们就介绍到这里了,其他相关的技术,感兴趣的小伙伴可以关注底部Debug的技术公众号,或者加Debug的微信,拉你进“微信版”的真正技术交流群!一起学习、共同成长!

补充:

1、本文涉及到的相关的源代码可以到此地址,check出来进行查看学习:

https://gitee.com/steadyjack/SpringBootTechnology

2、最近Debug发布了几门重量级的课程,感兴趣的小伙伴可以前往观看学习:
(1) 缓存中间件Redis技术入门与应用场景实战(SpringBoot2.x + 抢红包系统设计与实战) 
https://www.fightjava.com/web/index/course/detail/12

(2)  企业权限管理平台(SpringBoot2.0+Shiro+Vue+Mybatis)
https://www.fightjava.com/web/index/course/detail/8

3、关注一下Debug的技术微信公众号,最新的技术文章、课程以及技术专栏将会第一时间在公众号发布哦!