0%

Spring Boot 集成 MongoDB,看这一篇就够了

介绍如何在 Spring Boot 中集成 MongoDB,以及一些常见操作的示例代码

开发环境

CentOS 7.6 64位
MongoDB 3.6.3
JDK 1.8.0_201

安装 MongoDB

如下两种方式任选其一:
Docker安装MongoDB
Centos 7 离线安装 MongoDB 3.6.3

Spring Boot 集成 MongoDB

添加 Maven 依赖

pox.xml文件中添加spring-boot-starter-data-mongodb依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

配置

application.yml中添加如下配置内容

1
2
3
4
5
6
7
8
9
10
11
spring:
data:
mongodb:
# 方式 1
uri: mongodb://test:123456@172.16.22.30:27017/myDatabase
# 方式 2
host: 172.16.22.30
port: 27017
database: myDatabase
username: test
password: 123456

其中方式 1是标准 URI 连接语法,格式如下:

1
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
  • mongodb:// 这是固定的格式,必须要指定。
  • username:password@ 用户名、密码,可选项。
  • host1 必须的指定至少一个host, host1 是这个URI唯一要填写的。它指定了要连接服务器的地址。如果要连接复制集,请指定多个主机地址。
  • portX 可选的指定端口,如果不填,默认为27017
  • /database 指定数据库,若不指定,默认打开 test 数据库。
  • ?options 是连接选项。如果不使用/database,则前面需要加上/。所有连接选项都是键值对name=value,键值对之间通过&;(分号)隔开。

方式 1方式 2任选其一即可,如果两种方式都存在,只有方式 1会生效。

创建实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package cn.segon.springboot.mongodb.entity;

import lombok.Data;
import org.springframework.data.annotation.Id;

/**
* @author segon.xing
* @date 2020/3/31
*/
@Data
public class UserTest {

@Id
private String id;

/**
* 名字
*/
private String name;

/**
* 年龄
*/
private Integer age;
}

这里用lombok@Data注解实现了SetterGetter方法。
注意在id字段上有@Id注解,文档的唯一标识,在 MongoDB 中为ObjectId类型,它是唯一的,通过时间戳 + 机器标识 + 进程ID + 自增计数器构成。

创建 Service 类

本文是用MongoTemplate来操作数据库的,除了MongoTemplate还可以用MongoRepository的方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package cn.segon.springboot.mongodb.service.impl;

import cn.segon.springboot.mongodb.entity.User;
import cn.segon.springboot.mongodb.service.IUserService;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;

/**
* @author segon.xing
* @date 2020/3/31
*/
@Service
@Slf4j
public class UserServiceImpl implements IUserService {

@Autowired
private MongoTemplate mongoTemplate;

/**
* 添加
*/
@Override
public void add(User user) {
mongoTemplate.save(user);
}

/**
* 查询所有
*/
@Override
public List<User> findAll() {
return mongoTemplate.findAll(User.class);
}
}

创建 Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package cn.segon.springboot.mongodb.controller;

import cn.segon.springboot.mongodb.entity.User;
import cn.segon.springboot.mongodb.service.IUserService;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @author segon.xing
* @date 2020/3/31
*/
@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
private IUserService userService;

@PostMapping("/add")
public String add(@RequestBody User user) {
userService.add(user);

return "success";
}

@GetMapping("/list")
public String listAll() {
return JSON.toJSONString(userService.listAll());
}
}

测试

启动程序,然后通过Postman 访问添加用户接口
postman
可以看到返回了”success”,然后我们去MongoDB里看看数据是否存在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@172 ~]# mongo
MongoDB shell version v3.6.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.15
>
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
myDatabase 0.000GB
>
> use myDatabase
switched to db myDatabase
>
> show collections
user
>
> db.user.find()
{ "_id" : ObjectId("5e846c6b47e311376d6df8e7"), "name" : "segon", "age" : 18, "_class" : "cn.segon.springboot.mongodb.entity.User" }
>

可以看到数据库myDatabase和集合user都被自动创建了,并且user中存在刚刚插入的数据。

常用操作

添加一个文档

1
2
3
public void add(User user) {
mongoTemplate.save(user);
}

删除一个文档

1
2
3
4
// 注意 user 是查询出来的文档,即 user 中的 id 要存在
public void deleteUser(User user) {
mongoTemplate.remove(user);
}

根据条件删除文档

1
2
3
4
public void deleteUserById(String id) {
Query query = new Query(Criteria.where("_id").is(id));
mongoTemplate.remove(query, User.class);
}

查询所有文档

1
2
3
public List<User> findAll() {
return mongoTemplate.findAll(User.class);
}

单个条件查询

1
2
3
4
5
6
7
8
9
public void deleteUserById(String id) {
Query query = new Query(Criteria.where("_id").is(id));
mongoTemplate.remove(query, User.class);
}

public User getUserByName(String name) {
Query query = new Query(Criteria.where("name").is(name));
return mongoTemplate.findOne(query, User.class);
}

多个条件查询

1
2
3
4
public User getUserByNameAndAge(String name, Integer age) {
Query query = new Query(Criteria.where("name").is(name).and("age").is(age));
return mongoTemplate.findOne(query, User.class);
}

范围查询

1
2
3
4
public List<User> findUserByAgeRange(Integer min, Integer max) {
Query query = new Query(Criteria.where("age").gte(min).lte(max));
return mongoTemplate.find(query, User.class);
}

更新

注意三种更新方式根据实际需要选择一种

1
2
3
4
5
6
7
8
9
10
11
12
13
public void updateUser(String name, String newName, Integer newAge) {
// 查询条件
Query query = new Query(Criteria.where("name").is(name));
// 要更新的字段
Update update = new Update().set("name", newName).set("age", newAge);

// 1: updateFirst 更新查询返回结果集的第一条
mongoTemplate.updateFirst(query, update, User.class);
// 2: updateMulti 更新查询返回结果集的全部
mongoTemplate.updateMulti(query, update, User.class);
// 3: upsert 更新对象不存在则去添加
mongoTemplate.upsert(query, update, User.class);
}

排序

1
2
3
4
5
6
7
8
9
public List<User> findUserByAgeRange(Integer min, Integer max) {
Query query = new Query(Criteria.where("age").gte(min).lte(max));
query.with(Sort.by(
Sort.Order.asc("name"),
Sort.Order.desc("age")
));

return mongoTemplate.find(query, User.class);
}

常用注解

@Id

主键,不可重复,自带索引,可以在定义的列名上标注,可以自己定义生成规则,如果自己不设置@Id主键,MongoDB 会自动生成一个唯一主键,并且插入时效率远高于自己设置主键,在实际业务中不建议自己设置主键,应交给mongo自己生成,自己可以设置一个业务id,如int型字段,用自己设置的业务id来维护相关联的表。

@Document

标注在实体类上,表明由 MongoDB 来维护该表

1
2
3
4
5
6
7
8
9
10
/**
* 把一个java类声明为 MongoDB 的文档,可以通过 collection 参数指定这个类对应的文档
* 若未加 @Document,该 bean 保存到 MongoDB 的 "user" 文档
* 若添加 @Document,该 bean 保存到 MongoDB 指定的 "reUser" 文档
*/
@Document(collation = "reUser")
@Data
public class User {

}

@Field

代表一个字段,可以不加,不加的话默认以参数名为列名。

1
2
3
4
5
6
7
/**
* 给映射存储到 MongoDB 的字段取别名
* 若未加 @Field,该字段储存到文档中的 Key 为 "name"
* 若添加 @Field,该字段储存到文档中的 Key 为指定的 "reName"
*/
@Field("reName")
private String name;

@Transient

被该注解标注的,将不会被录入到数据库中,只作为普通的 javaBean 属性。