# springboot2-mongodb-demo
**Repository Path**: knowz/springboot2-mongodb-demo
## Basic Information
- **Project Name**: springboot2-mongodb-demo
- **Description**: springboot2整合MongoDB4.0与事务实现
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 7
- **Forks**: 8
- **Created**: 2018-08-12
- **Last Updated**: 2020-12-18
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# springboot2-mongodb-demo
#### 项目介绍
- springboot2.0.4
- MongoDB4.0.1数据库
- 实现了MongoDB的事务
#### 使用说明
1. 导入MongoDB的依赖
```
org.springframework.boot
spring-boot-starter-data-mongodb
```
2. 配置MongoDB的连接
```
spring.data.mongodb.uri=mongodb://username:password@localhost:27017/test
```
3. 编写pojo类
当id设置为 **ObjectId** 类型和添加 **@Id** 注解时时,MongoDB数据库会自动生成主键,我们在保存对象时就不用设置id的值
```
package com.zkane.domain;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
/**
* @author 594781919@qq.com
* @date 2018/8/12
*/
@Data
public class Employee {
@Id
private ObjectId id;
private String name;
private Integer age;
}
```
4. 编写dao层的方法
jpa支持很多方法命名规则来自动生成查询语句
```
package com.zkane.repository;
import com.zkane.domain.Employee;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;
/**
* @author 594781919@qq.com
* @date 2018/8/12
*/
public interface EmpRepository extends MongoRepository {
Employee findByName(String name);
List findByAgeGreaterThan(int age);
}
```


5. 测试
```
package com.zkane;
import com.zkane.domain.Employee;
import com.zkane.repository.EmpRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Springboot2MongodbDemoApplicationTests {
@Autowired
private EmpRepository empRepository;
@Autowired
private MongoTemplate mongoTemplate;
@Test
public void test1() {
Employee employee = new Employee();
employee.setName("王五");
employee.setAge(29);
empRepository.save(employee);
System.out.println(employee);
}
@Test
public void test2() {
Employee employee = empRepository.findByName("张三");
System.out.println(employee);
}
@Test
public void test3() {
// 通过MongoTemplate来查询数据
Query query = new Query(Criteria.where("age").in(20, 23));
List employees = mongoTemplate.find(query, Employee.class);
System.out.println(employees);
}
@Test
public void test4() {
// 查询年龄大于25的数据
List employeeList = empRepository.findByAgeGreaterThan(25);
System.out.println(employeeList);
}
}
```
#### MongoDB的事务
1. 目前事务回滚只能在复制集上操作,单独的mongodb server不能操作事务
- 开启服务器27017
```
D:\Program Files\MongoDB\Server\4.0\bin> .\mongod.exe -dbpath ..\data\db --replSet rs0
```
- 开启服务器27018
```
D:\Program Files\MongoDB\Server\4.0\bin> .\mongod.exe -dbpath ..\data\db27018 --port 27018 --replSet rs0
```
- 设置集群
```
D:\Program Files\MongoDB\Server\4.0\bin> .\mongo.exe --port 27017
> rs.initiate()
rs0:SECONDARY> rs.add('localhost:27018')
```
2.代码实现
- 修改导入的依赖
```
org.springframework.boot
spring-boot-starter-data-mongodb
org.mongodb
mongodb-driver
org.mongodb
mongo-java-driver
3.8.0
com.alibaba
fastjson
1.2.47
```
- 测试代码
```
package com.zkane.service;
import com.alibaba.fastjson.JSONObject;
import com.mongodb.MongoClient;
import com.mongodb.MongoException;
import com.mongodb.client.ClientSession;
import com.mongodb.client.MongoCollection;
import com.zkane.domain.Address;
import com.zkane.domain.Employee;
import com.zkane.repository.EmpRepository;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author: 594781919@qq.com
* @date: 2018/8/13
*/
@Service
public class EmployeeService {
@Autowired
private EmpRepository empRepository;
@Autowired
private MongoClient client;
/**
* 测验MongoDB的事务回滚
*/
public void save() {
try (ClientSession clientSession = client.startSession()) {
clientSession.startTransaction();
Employee employee = new Employee();
employee.setName("王五");
employee.setAge(31);
Address address = new Address();
address.setCity("北京");
address.setStreet("长安路");
employee.setAddress(address);
MongoCollection employeeCollection = client.getDatabase("test").getCollection("employee");
employeeCollection.insertOne(clientSession, Document.parse(JSONObject.toJSONString(employee)));
//int i = 1 / 0;
employee = new Employee();
employee.setName("赵六");
employee.setAge(25);
address = new Address();
address.setCity("北京");
address.setStreet("太升路");
employee.setAddress(address);
employeeCollection.insertOne(clientSession, Document.parse(JSONObject.toJSONString(employee)));
commitWithRetry(clientSession);
}
}
/**
* 提交失败时,进行重新提交
* @param clientSession
*/
void commitWithRetry(ClientSession clientSession) {
while (true) {
try {
clientSession.commitTransaction();
System.out.println("Transaction committed");
break;
} catch (MongoException e) {
// can retry commit
if (e.hasErrorLabel(MongoException.UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL)) {
System.out.println("UnknownTransactionCommitResult, retrying commit operation ...");
continue;
} else {
System.out.println("Exception during commit ...");
throw e;
}
}
}
}
}
```