Springboot整合MongoDB - Alias的博客

Springboot整合MongoDB

导入依赖

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

添加配置文件

1
mongodb://username:password@host1:port1,host2:port2,...,hostN:portN/database?options

参数说明:

  • mongodb://:这是固定的格式,必须要指定
  • username:password@:可选项,如果设置,在连接数据库服务器之后,驱动都会尝试登录这个数据库
  • host1:port1:主机IP和端口号,必须指定至少一个host。如果要连接复制集,请指定多个主机地址
  • /database:如果指定了username:password@,连接时会验证并登录指定数据库。若不指定,默认打开 test 数据库
  • ?options:连接可选项,例如connectTimeoutMS=5000ms,表示连接等待时间最长 5 秒

无密码连接使用test数据库

1
mongodb://127.0.0.1:27017/test
1
2
3
4
5
# 应用名称
spring.application.name=springboot-mongo
# 应用服务 WEB 访问端口
server.port=8080
spring.data.mongodb.uri=mongodb://127.0.0.1:27017/test

创建实体类

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
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.io.Serializable;
import java.util.Date;

/**
* @author lisihan
* @Description Person实体类 使用@Document注解指定集合名称
* @date 2022/11/3-21:47
*/
@Document(collection="persons")
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Person implements Serializable {
private static final long serialVersionUID = -3258839839160856613L;
/**
* 使用@Id注解指定MongoDB中的 _id 主键
*/
@Id
private Long id;
private String userName;
private String passWord;
private Integer age;
private Date createTime;
}

插入文档

没指定集合名称时,会取@Document注解中的集合名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Autowired
private MongoTemplate mongoTemplate;
/**
* 插入文档
*/
@Test
public void insert(){
Person person =new Person();
person.setId(1l);
person.setUserName("张三");
person.setPassWord("123456");
person.setCreateTime(new Date());
mongoTemplate.insert(person);
}

自定义集合名称插入

1
2
3
4
5
6
7
8
9
@Test
public void insertCustomCollection(){
Person person =new Person();
person.setId(1l);
person.setUserName("张三");
person.setPassWord("123456");
person.setCreateTime(new Date());
mongoTemplate.insert(person, "custom_person");
}

自定义集合并批量插入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 自定义集合,批量插入文档
*/
@Test
public void insertBatch(){
List<Person> personList = new ArrayList<>();
Person person1 =new Person();
person1.setId(10l);
person1.setUserName("张三");
person1.setPassWord("123456");
person1.setCreateTime(new Date());
personList.add(person1);
Person person2 =new Person();
person2.setId(11l);
person2.setUserName("李四");
person2.setPassWord("123456");
person2.setCreateTime(new Date());
personList.add(person2);
mongoTemplate.insert(personList, "custom_person");
}

存储文档

在存储文档的时候会通过主键ID进行判断,如果存在就更新,否则就插入

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 存储文档,如果没有插入,否则更新
*/
@Test
public void save(){
Person person =new Person();
person.setId(13l);
person.setUserName("王五");
person.setPassWord("123456");
person.setAge(35);
person.setCreateTime(new Date());
mongoTemplate.save(person);
}

自定义集合存储文档

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 自定义集合,存储文档
*/
@Test
public void saveCustomCollection(){
Person person =new Person();
person.setId(1l);
person.setUserName("张三");
person.setPassWord("123456");
person.setCreateTime(new Date());
mongoTemplate.save(person, "custom_person");
}

更新文档

MongoTemplate提供了updateFirst()updateMulti()方法,用于更新文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 更新文档,匹配查询到的文档数据中的第一条数据
*/
@Test
public void updateFirst(){
//更新对象
Person person =new Person();
person.setId(1l);
person.setUserName("张三123");
person.setPassWord("123456");
person.setCreateTime(new Date());
//更新条件
Query query= new Query(Criteria.where("id").is(person.getId()));
//更新值
Update update= new Update().set("userName", person.getUserName()).set("passWord", person.getPassWord());
//更新查询满足条件的文档数据(第一条)
UpdateResult result =mongoTemplate.updateFirst(query,update, Person.class);
if(result!=null){
System.out.println("更新条数:" + result.getMatchedCount());
}
}

更新文档,匹配查询到的文档数据中的所有数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 更新文档,匹配查询到的文档数据中的所有数据
* @throws Exception
*/
@Test
public void updateMany() throws Exception {
//更新对象
Person person =new Person();
person.setId(1l);
person.setUserName("张三");
person.setPassWord("123456");
person.setCreateTime(new Date());
//更新条件
Query query= new Query(Criteria.where("id").is(person.getId()));
//更新值
Update update= new Update().set("userName", person.getUserName()).set("passWord", person.getPassWord());
//更新查询满足条件的文档数据(全部)
UpdateResult result = mongoTemplate.updateMulti(query, update, Person.class);
if(result!=null){
System.out.println("更新条数:" + result.getMatchedCount());
}
}

删除文档

MongoTemplate提供了remove()findAndRemove()findAllAndRemove()方法,用于删除文档

删除符合条件的所有文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 删除符合条件的所有文档
* @throws Exception
*/
@Test
public void remove() throws Exception {
Person person =new Person();
person.setId(1l);
person.setUserName("张三");
person.setPassWord("123456");
person.setCreateTime(new Date());
Query query = new Query(Criteria.where("userName").is(person.getUserName()));
DeleteResult result = mongoTemplate.remove(query, Person.class);
System.out.println("删除条数:" + result.getDeletedCount());
}

删除符合条件的单个文档,并返回删除的文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 删除符合条件的单个文档,并返回删除的文档
* @throws Exception
*/
@Test
public void findAndRemove() throws Exception {
Person person =new Person();
person.setId(1l);
person.setUserName("张三");
person.setPassWord("123456");
person.setCreateTime(new Date());
Query query = new Query(Criteria.where("id").is(person.getId()));
Person result = mongoTemplate.findAndRemove(query, Person.class);
System.out.println("删除的文档数据:" + result.toString());
}

删除符合条件的所有文档,并返回删除的文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 删除符合条件的所有文档,并返回删除的文档
* @throws Exception
*/
@Test
public void findAllAndRemove() throws Exception {
Person person =new Person();
person.setId(1l);
person.setUserName("张三");
person.setPassWord("123456");
person.setCreateTime(new Date());
Query query = new Query(Criteria.where("id").is(person.getId()));
List<Person> result = mongoTemplate.findAllAndRemove(query, Person.class);
System.out.println("删除的文档数据:" + result.toString());
}

查询文档

MongoTemplate提供了非常多的文档查询方法,日常开发中用的最多的就是find()方法

查询集合中的全部文档数据

1
2
3
4
5
@Test
public void findAll() throws Exception {
List<Person> result = mongoTemplate.findAll(Person.class);
System.out.println("查询结果:" + result.toString());
}

查询集合中指定的ID文档数据

1
2
3
4
5
6
@Test
public void findById() {
long id = 1l;
Person result = mongoTemplate.findById(id, Person.class);
System.out.println("查询结果:" + result.toString());
}

根据条件查询集合中符合条件的文档,返回第一条数据

1
2
3
4
5
6
7
@Test
public void findOne() {
String userName = "张三";
Query query = new Query(Criteria.where("userName").is(userName));
Person result = mongoTemplate.findOne(query, Person.class);
System.out.println("查询结果:" + result.toString());
}

根据条件查询集合中符合条件的文档

1
2
3
4
5
6
7
@Test
public void findByCondition() {
String userName = "张三";
Query query = new Query(Criteria.where("userName").is(userName));
List<Person> result = mongoTemplate.find(query, Person.class);
System.out.println("查询结果:" + result.toString());
}

根据【AND】关联多个查询条件,查询集合中的文档数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 根据【AND】关联多个查询条件,查询集合中的文档数据
*/
@Test
public void findByAndCondition() {
// 创建条件
Criteria criteriaUserName = Criteria.where("userName").is("张三");
Criteria criteriaPassWord = Criteria.where("passWord").is("123456");
// 创建条件对象,将上面条件进行 AND 关联
Criteria criteria = new Criteria().andOperator(criteriaUserName, criteriaPassWord);
// 创建查询对象,然后将条件对象添加到其中
Query query = new Query(criteria);
List<Person> result = mongoTemplate.find(query, Person.class);
System.out.println("查询结果:" + result.toString());
}

根据【OR】关联多个查询条件,查询集合中的文档数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 根据【OR】关联多个查询条件,查询集合中的文档数据
*/
@Test
public void findByOrCondition() {
// 创建条件
Criteria criteriaUserName = Criteria.where("userName").is("张三");
Criteria criteriaPassWord = Criteria.where("passWord").is("123456");
// 创建条件对象,将上面条件进行 OR 关联
Criteria criteria = new Criteria().orOperator(criteriaUserName, criteriaPassWord);
// 创建查询对象,然后将条件对象添加到其中
Query query = new Query(criteria);
List<Person> result = mongoTemplate.find(query, Person.class);
System.out.println("查询结果:" + result.toString());
}

根据【IN】关联多个查询条件,查询集合中的文档数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 根据【IN】关联多个查询条件,查询集合中的文档数据
*/
@Test
public void findByInCondition() {
// 设置查询条件参数
List<Long> ids = Arrays.asList(1l, 10l, 11l);
// 创建条件
Criteria criteria = Criteria.where("id").in(ids);
// 创建查询对象,然后将条件对象添加到其中
Query query = new Query(criteria);
List<Person> result = mongoTemplate.find(query, Person.class);
System.out.println("查询结果:" + result.toString());
}

根据【逻辑运算符】查询集合中的文档数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 根据【逻辑运算符】查询集合中的文档数据
*/
@Test
public void findByOperator() {
// 设置查询条件参数
int min = 20;
int max = 35;
Criteria criteria = Criteria.where("age").gt(min).lte(max);
// 创建查询对象,然后将条件对象添加到其中
Query query = new Query(criteria);
List<Person> result = mongoTemplate.find(query, Person.class);
System.out.println("查询结果:" + result.toString());
}

根据【正则表达式】查询集合中的文档数据

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 根据【正则表达式】查询集合中的文档数据
*/
@Test
public void findByRegex() {
// 设置查询条件参数
String regex = "^张*";
Criteria criteria = Criteria.where("userName").regex(regex);
// 创建查询对象,然后将条件对象添加到其中
Query query = new Query(criteria);
List<Person> result = mongoTemplate.find(query, Person.class);
System.out.println("查询结果:" + result.toString());
}

根据条件查询集合中符合条件的文档,获取其文档列表并排序

1
2
3
4
5
6
7
8
9
10
/**
* 根据条件查询集合中符合条件的文档,获取其文档列表并排序
*/
@Test
public void findByConditionAndSort() {
String userName = "张三";
Query query = new Query(Criteria.where("userName").is(userName)).with(Sort.by("age"));
List<Person> result = mongoTemplate.find(query, Person.class);
System.out.println("查询结果:" + result.toString());
}

根据单个条件查询集合中的文档数据,并按指定字段进行排序与限制指定数目

1
2
3
4
5
6
7
8
@Test
public void findByConditionAndSortLimit() {
String userName = "张三";
//从第一行开始,查询2条数据返回
Query query = new Query(Criteria.where("userName").is(userName)).with(Sort.by("createTime")).limit(2).skip(1);
List<Person> result = mongoTemplate.find(query, Person.class);
System.out.println("查询结果:" + result.toString());
}

统计集合中符合【查询条件】的文档【数量】

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 统计集合中符合【查询条件】的文档【数量】
*/
@Test
public void countNumber() {
// 设置查询条件参数
String regex = "^张*";
Criteria criteria = Criteria.where("userName").regex(regex);
// 创建查询对象,然后将条件对象添加到其中
Query query = new Query(criteria);
long count = mongoTemplate.count(query, Person.class);
System.out.println("统计结果:" + count);
}

创建索引

索引在所有的数据库中,暂居的位置非常重要,例如当你检索一张上百万的数据表的时候,如果没走索引,查询效率会极其缓慢,对于 MongoDB 来说,同样如此。

创建升序索引

1
2
3
4
5
6
7
8
9
10
/**
* 创建升序索引
*/
@Test
public void createAscendingIndex() {
// 设置字段名称
String field = "userName";
// 创建索引
mongoTemplate.getCollection("persons").createIndex(Indexes.ascending(field));
}

移除索引

1
2
3
4
5
6
7
8
9
10
/**
* 根据索引名称移除索引
*/
@Test
public void removeIndex() {
// 设置字段名称
String field = "userName";
// 删除索引
mongoTemplate.getCollection("persons").dropIndex(field);
}

查询集合中所有的索引

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 查询集合中所有的索引
*/
@Test
public void getIndexAll() {
// 获取集合中所有列表
ListIndexesIterable<Document> indexList = mongoTemplate.getCollection("persons").listIndexes();
// 获取集合中全部索引信息
for (Document document : indexList) {
System.out.println("索引列表:" + document);
}
}

我们还可以通过在实体类上加注解方式来创建索引

1
2
3
4
5
/**
* 创建一个5秒之后文档自动删除的索引
*/
@Indexed(expireAfterSeconds=5)
private Date createTime;

MongoDB中的事务

单节点 mongodb 不支持事务,需要搭建 MongoDB 复制集。

1
2
3
4
5
6
7
8
9
10
11
/**
* 配置事务管理器
*
*/
@Configuration
public class TransactionConfig {
@Bean
MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
}
}

事务服务测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Service
public class TransactionExample {
@Autowired
private MongoTemplate mongoTemplate;
@Transactional(rollbackFor = Exception.class)
public Object transactionTest(){
Person person =new Person();
person.setId(1l);
person.setUserName("张三");
person.setPassWord("123456");
person.setCreateTime(new Date());
Person newPerson = mongoTemplate.insert(person);
// 抛出异常,观察数据是否进行回滚
if(1 == 1){
throw new RuntimeException("异常");
}
return newPerson;
}
}

评论