介绍MongoDB与Spring Boo集成,并通过MongoRepository以及MongoTemplate来执行CRUD操作。
Spring Boot:2.3.0.RELEASE Spring Boot Data MongoDB:2.3.0.RELEASE MongoDB:4.2.6 MongoDB Driver:4.0.3
CRUD示例数据结构
Department: String id String name String description Array employees
Employee: String empId String name int age double salary
one to many relationships
安装MongoDB
docker-compose.yml ```yaml version: ‘3’ services: mongodb: container_name: “mongodb” image: “mongo:latest” environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: example ports:
- 27017:27017logging:driver: "json-file"options:max-size: "50m"
安装并启动```bash/usr/local/bin/docker-compose -f /Users/chou/Documents/work/projects/demo/springboot-demo/springboot-mongodb/docker-compose.yml up -d mongodb
创建Spring Boot项目
略
添加Mongo依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>
Spring application配置
application.properties
spring.data.mongodb.username=rootspring.data.mongodb.password=examplespring.data.mongodb.database=admin
测试能否正常启动
host:localhost port:27017 database:admin user:root password:example
项目结构
创建Domain Object
package com.example.mongodb.model;import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.index.Indexed;import org.springframework.data.mongodb.core.mapping.Document;import java.util.List;@Document("Department")public class Department {@Idprivate String id;@Indexed(name = "deptName")private String name;private String description;@DBRefprivate List<Employee> employees;//...getter setter}
package com.example.mongodb.model;import org.springframework.data.annotation.Id;import org.springframework.data.mongodb.core.mapping.Document;@Document("Employee")public class Employee {@Idprivate String empId;private String name;private int age;private double salary;//...getter setter}
@Document 标识了要持久化到mongodb的DO。
@Id 文档的唯一标识,在mongodb中是objectId。
@DbRef 关联另一个Document对象,存入的是文档的引用,如果不使用这个注解,存入的是内容。不过即使使用@DbRef,mongodb本身并不维护关联数据,也就是说需要手动将数据插入到被关联文档。
两种操作数据的方式
MongoRepository
package com.example.mongodb.repository;import com.example.mongodb.model.Department;import org.springframework.data.mongodb.repository.MongoRepository;import org.springframework.data.mongodb.repository.Query;import org.springframework.stereotype.Repository;import java.util.List;@Repositorypublic interface DepartmentRepository extends MongoRepository<Department,String> {@Query(value = "{'Employee.name': ?0}", fields = "{'employees' : 0}")Department findDepartmentByEmployeeName(String empName);List<Department> findDepartmentByName(String name);}
MongoTemplate
package com.example.mongodb.repository;import com.example.mongodb.model.Department;import org.springframework.beans.factory.annotation.Autowired;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.data.mongodb.core.query.Update;import org.springframework.stereotype.Repository;import java.util.List;@Repositorypublic class DeptRepository {@Autowiredprivate MongoTemplate mongoTemplate;public List<Department> findAll() {return mongoTemplate.findAll(Department.class);}public List<Department> findDepartmentByName(String deptName){Query query = new Query();query.addCriteria(Criteria.where("name").is(deptName));return mongoTemplate.find(query, Department.class);}public Department save(Department department) {mongoTemplate.save(department);return department;}public Department update(Department department){Query query = new Query();query.addCriteria(Criteria.where("id").is(department.getId()));Update update = new Update();update.set("name", department.getName());update.set("description", department.getDescription());return mongoTemplate.findAndModify(query, update, Department.class);}public void deleteById(String deptId) {Query query = new Query();query.addCriteria(Criteria.where("id").is(deptId));mongoTemplate.remove(query, Department.class);}}
创建Controller
package com.example.mongodb.controller;import com.example.mongodb.model.Department;import com.example.mongodb.model.Employee;import com.example.mongodb.repository.DepartmentRepository;import com.example.mongodb.repository.DeptRepository;import com.example.mongodb.repository.EmpRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import java.util.Collections;import java.util.List;import java.util.Optional;@RestControllerpublic class DepartmentController {@AutowiredDepartmentRepository departmentRepository;@AutowiredDeptRepository deptRepository;@AutowiredEmpRepository empRepository;@PostMapping("/v1/dept/s")public Department v1save(@RequestBody Department department) {List<Employee> employees = Optional.ofNullable(department.getEmployees()).orElse(Collections.emptyList());employees.forEach(employee -> empRepository.save(employee));return departmentRepository.save(department);}@GetMapping("/v1/dept/l")public List<Department> v1list(){return departmentRepository.findAll();}@PutMapping("/v1/dept/u/{deptId}")public Department v1update(@RequestBody Department department, @PathVariable String deptId) {department.setId(deptId);List<Employee> employees = Optional.ofNullable(department.getEmployees()).orElse(Collections.emptyList());employees.forEach(employee -> empRepository.save(employee));return departmentRepository.save(department);}@DeleteMapping("/v1/dept/d/{deptId}")public String v1delete(@PathVariable String deptId) {departmentRepository.deleteById(deptId);return deptId;}@GetMapping("/v1/dept/get/{deptName}")public List<Department> v1getByName(@PathVariable String deptName) {return departmentRepository.findDepartmentByName(deptName);}@GetMapping("/v1/dept/get/emp/{empName}")public Department v1getByEmpName(@PathVariable String empName) {return departmentRepository.findDepartmentByEmployeeName(empName);}@PostMapping("/v2/dept/s")public Department v2save(Department department) {List<Employee> employees = Optional.ofNullable(department.getEmployees()).orElse(Collections.emptyList());employees.forEach(employee -> empRepository.save(employee));return deptRepository.save(department);}@GetMapping("/v2/dept/l")public List<Department> v2list() {return deptRepository.findAll();}@PutMapping("/v2/dept/u")public Department v2update(Department department){List<Employee> employees = Optional.ofNullable(department.getEmployees()).orElse(Collections.emptyList());employees.forEach(employee -> empRepository.save(employee));return deptRepository.update(department);}@DeleteMapping("/v2/dept/d/{deptId}")public void v2delete(@PathVariable String deptId) {deptRepository.deleteById(deptId);}@GetMapping("/v2/dept/get/{deptName}")public List<Department> v2getByName(@PathVariable String deptName){return deptRepository.findDepartmentByName(deptName);}}
v1的接口使用MongoRepository方式操作数据,v2的接口使用MonoTemplate方式操作数据。
测试
###新增POST http://localhost:8080/v1/dept/sContent-Type: application/json{"id": "10010","name": "中国联通","description": "中国联通","employees": [{"empId": "1","name": "jack ma","age": 78,"salary": 900000.0}]}###更新PUT http://localhost:8080/v1/dept/u/10010Content-Type: application/json{"id": "10010","name": "中国联通","description": "中国联通","employees": [{"empId": "1","name": "jack ma","age": 78,"salary": 900000.0},{"empId": "2","name": "pony ma","age": 78,"salary": 900000.0}]}###删除DELETE http://localhost:8080/v1/dept/d/10010###查询GET http://localhost:8080/v1/dept/l


