来源:
https://mrbird.cc/Spring-Boot-Mongo-DB-CRUD.html
这节我们将整合Spring Boot与Mongo DB实现增删改查的功能,并且实现序列递增。Mongo DB下载地址:https://www.mongodb.com/download-center/community。Mongo DB的基本介绍和增删改查的用法可以参考我之前的文章: MongoDB shell 、 MongoDB文档CUD 和 MongoDB 文档查询 。
新建一个Spring Boot项目,版本为2.1.3.RELEASE,并引入如下依赖:
1<dependency>
2 <groupId>org.springframework.bootgroupId>
3 <artifactId>spring-boot-starter-data-mongodbartifactId>
4dependency>
5<dependency>
6 <groupId>org.springframework.bootgroupId>
7 <artifactId>spring-boot-starter-webartifactId>
8dependency>
然后可以通过Mongo Shell或者Mongo Compass工具创建一个名称为testdb的数据库,并新增user文档(文档,类似与关系型数据库里的数据表):
![87fbdcd50156d0035c2a6cea2e75473d.png](https://i-blog.csdnimg.cn/blog_migrate/302a9f295a9e61d01ead81e49993e916.png)
在配置文件application.yml里配置Mongo DB:
1spring:
2 data:
3 mongodb:
4 host: localhost
5 port: 27017
6 database: testdb
Mongo DB的默认端口为27017,使用的数据库为刚刚创建的testdb。
创建User实体类:
1@Document(collection = "user")
2public class User {
3
4 @Id
5 private String id;
6
7 private String name;
8
9 private Integer age;
10
11 private String description;
12
13 // get set 略
14}
@Document(collection = "user")
表明这是一个文档对象,名称为user
,对应Mongo DB里的user表。@Id
标注主键字段,String类型的主键值在插入的时候Mongo DB会帮我们自动生成。如果对象中的某个属性为非表字段,可以使用注解@Transient
进行排除。
准备好这些后,我们开始编写一些简单的增删改查样例。
简单增删改查
创建一个UserDao接口:
1@Repository
2public interface UserDao extends MongoRepository<User, String> {
3}
接口继承自MongoRepository
,泛型分别为实体对象和主键类型。通过继承MongoRepository
,UserDao
包含了一些增删改查的方法,如下图所示:
![6d1da33ed8c058d824396507a6476a99.png](https://i-blog.csdnimg.cn/blog_migrate/562a18a77ceda099bc2b6611e204f717.png)
接着编写UserService,为了方便这里不再编写接口:
1@Service
2public class UserService {
3
4 @Autowired
5 private UserDao userDao;
6
7 public List getUsers() { 8 return userDao.findAll(); 9 }1011 public Optional getUser(String id) {12 return this.userDao.findById(id);13 }1415 /**16 * 新增和修改都是 save方法,17 * id 存在为修改,id 不存在为新增18 */19 public User createUser(User user) {20 user.setId(null);21 return userDao.save(user);22 }2324 public void deleteUser(String id) {25 this.userDao.findById(id)26 .ifPresent(user -> this.userDao.delete(user));27 }2829 public void updateUser(String id, User user) {30 this.userDao.findById(id)31 .ifPresent(32 u -> {33 u.setName(user.getName());34 u.setAge(user.getAge());35 u.setDescription(user.getDescription());36 this.userDao.save(u);37 }38 );39 }40}
上面我们编写了基本的增删改查样例,新增和修改都是通过save
方法完成的,当主键存在时则为修改,主键不存在则为新增。
最后编写一个RESTful的UserController(为了方便,没有对参数进行校验):
1@RestController
2@RequestMapping("user")
3public class UserController {
4
5 @Autowired
6 private UserService userService;
7
8 @GetMapping
9 public List getUsers() {10 return userService.getUsers();11 }1213 @PostMapping14 public User createUser(User user) {15 return userService.createUser(user);16 }1718 @DeleteMapping("/{id}")19 public void deleteUser(@PathVariable String id) {20 userService.deleteUser(id);21 }2223 @PutMapping("/{id}")24 public void updateUser(@PathVariable String id, User user) {25 userService.updateUser(id, user);26 }2728 /**29 * 根据用户 id查找30 * 存在返回,不存在返回 null31 */32 @GetMapping("/{id}")33 public User getUser(@PathVariable String id) {34 return userService.getUser(id).orElse(null);35 }36}
启动项目,使用postman来测试接口的可用性。
测试新增用户:
![1064d7830e23df9f6de2b81f09a7d0a3.png](https://i-blog.csdnimg.cn/blog_migrate/0425e2eecab83709db811d2140d9397c.png)
新增成功,查看数据库:
![8339ebe9f997fe42a5a9ca4eb64d7af2.png](https://i-blog.csdnimg.cn/blog_migrate/90a97872941ae2429e1d6dad593da5ff.png)
测试查询用户:
![02bf981168148f2e3969792de34ea8af.png](https://i-blog.csdnimg.cn/blog_migrate/45dcdd17150802aa442607c6011c225e.png)
查询成功。
测试通过用ID查找用户:
![02ee4c8b04fe4f858c9d9b2fe2e71096.png](https://i-blog.csdnimg.cn/blog_migrate/168e7ed47014859909e10db0001583be.png)
更新用户:
![4112ee69d14c766ae83ccdff88520d2b.png](https://i-blog.csdnimg.cn/blog_migrate/34054fd15461b2a52c977e9e2c108ae2.png)
查看数据库是否更新成功:
![55bec14b688589b52be674d7bd9eb8a5.png](https://i-blog.csdnimg.cn/blog_migrate/f13816cd4dfc1deb1eff1581ccd96e80.png)
更新成功。
最后测试通过用户ID删除用户:
![ef2ae2449abb50dfdb31f0e78ad2fa26.png](https://i-blog.csdnimg.cn/blog_migrate/8bda4a4690cc4b01f02861b93f5efe3e.png)
返回状态码200,删除成功。
查看数据库,删除成功:
![36efa25389a09debd947c914f468b54c.png](https://i-blog.csdnimg.cn/blog_migrate/3737f1128e1079b58a264f08674727ab.png)
多条件查询
其实UserDao
通过继承MongoRepository
已经具有了JPA的特性,我们可以通过方法名来构建多查询条件的SQL。比如通过用户的年龄段来查询:
1@Repository
2public interface UserDao extends MongoRepository<User, String> {
3
4 /** 5 * 根据年龄段来查找 6 * 7 * @param from from 8 * @param to to 9 * @return List10 */
11 List findByAgeBetween(Integer from, Integer to);
12}
在输入findBy
后,IDEA会根据实体对象的属性和SQL的各种关键字自动组合提示:
![4e408dbb4361ec341232415bfbb8d518.png](https://i-blog.csdnimg.cn/blog_migrate/409f893afa4fdd961b3c797e0ba4deeb.png)
比如再在创建一个通过年龄段,用户名和描述(模糊查询)查询用户的方法:
1/**
2 * 通过年龄段,用户名,描述(模糊查询)
3 *
4 * @param from from
5 * @param to to
6 * @param name name
7 * @param description description
8 * @return List 9 */10List findByAgeBetweenAndNameEqualsAndDescriptionIsLike(Integer from, Integer to, String name, String description);
方法参数个数需要和方法名中所需要的参数个数对应上。
排序与分页
排序和分页需要使用MongoTemplate
对象来完成,在UserService
里新增一个getUserByCondition
方法:
1@Autowired
2private MongoTemplate template;
3
4public Page getUserByCondition(int size, int page, User user) { 5 Query query = new Query(); 6 Criteria criteria = new Criteria(); 7 8 if (!StringUtils.isEmpty(user.getName())) { 9 criteria.and("name").is(user.getName());10 }11 if (!StringUtils.isEmpty(user.getDescription())) {12 criteria.and("description").regex(user.getDescription());13 }1415 query.addCriteria(criteria);1617 Sort sort = new Sort(Sort.Direction.DESC, "age");18 Pageable pageable = PageRequest.of(page, size, sort);1920 List users = template.find(query.with(pageable), User.class);21 return PageableExecutionUtils.getPage(users, pageable, () -> template.count(query, User.class));22}
size
表示每页显示的条数,page
表示当前页码数,0表示第一页。上面的方法通过name
和description
(模糊查询)来查询用户分页信息,并且查询结果使用age
字段降序排序。方法返回Page
对象。
在UserController
里添加:
1@GetMapping("/condition")
2public Page getUserByCondition(int size, int page, User user) {
3 return userService.getUserByCondition(size, page, user);
4}
重启项目,我们往数据库里多加几条数据:
![f3956bedf840dfcc20780e07bbefb3a3.png](https://i-blog.csdnimg.cn/blog_migrate/2944892dbbaaf42a8ed6af9016cfb672.png)
获取第1页数据,每页显示10条:
![8a7a52b07a77fe9a3d2b719bf4a54bae.png](https://i-blog.csdnimg.cn/blog_migrate/cc7c87e9f4c5bb83250b482420b3c738.png)
返回数据:
1{
2 "content": [
3 {
4 "id": "5ca56ae2f08f0b6048fd470d",
5 "name": "jane",
6 "age": 26,
7 "description": "web developer"
8 },
9 {
10 "id": "5ca56ad1f08f0b6048fd470c",
11 "name": "scott",
12 "age": 23,
13 "description": "ui designer"
14 },
15 {
16 "id": "5ca56afaf08f0b6048fd470e",
17 "name": "mike",
18 "age": 21,
19 "description": "python developer"
20 },
21 {
22 "id": "5ca56b38f08f0b6048fd470f",
23 "name": "mrbird",
24 "age": 18,
25 "description": "java noob"
26 }
27 ],
28 "pageable": {
29 "sort": {
30 "sorted": true,
31 "unsorted": false,
32 "empty": false
33 },
34 "offset": 0,
35 "pageSize": 10,
36 "pageNumber": 0,
37 "unpaged": false,
38 "paged": true
39 },
40 "last": true,
41 "totalPages": 1,
42 "totalElements": 4,
43 "number": 0,
44 "size": 10,
45 "sort": {
46 "sorted": true,
47 "unsorted": false,
48 "empty": false
49 },
50 "numberOfElements": 4,
51 "first": true,
52 "empty": false
53}
剩下可以自己测试。
postman测试样例及源码链接:https://github.com/wuyouzhuguli/SpringAll/tree/master/56.Spring-Boot-MongoDB-crud
● 【图文讲解】你一定能看懂的HTTPS原理剖析!
● 基础面试,为什么面试官总喜欢问String?
● Spring Boot Admin 2.2.0发布,支持最新Spring Boot/Cloud之外,新增中文展示!
● 你应该知道的 @ConfigurationProperties 注解的使用姿势,这一篇就够了
● 学并发编程,透彻理解这三个核心是关键
● 读取Excel还用POI?试试这款开源工具
● 什么是读写锁?微服务注册中心是如何进行读写锁优化的?
● 使用 Spring Framework 时常犯的十大错误
● Lombok 使用详解,简化Java编程
● 用 Spring 的 BeanUtils 前,建议先了解这几个坑!
● 别在 Java 代码里乱打日志了,这才是打印日志的正确姿势!
● Mybatis:颠覆你心中对事务的理解!
● 面试官:你说 HashMap 线程不安全,它为啥不安全呢?
● ElasticSearch 亿级数据检索案例实战!
● Java 8 Stream Api 中的 peek 操作
● 【12张手绘图】我搞懂了微服务架构!
● 凌晨两点,IT人的朋友圈!
● Java 8 Stream Api 中的新操作
● SonarQube - 中文插件安装
● SonarQube 搭建好了,5分钟Docker搭建Maven私服
● 无套路,3分钟带你轻松上手SonarQube - 代码质量检测平台
如有收获,请帮忙转发,您的鼓励是作者最大的动力,谢谢!