介绍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:

  1. - 27017:27017
  2. logging:
  3. driver: "json-file"
  4. options:
  5. max-size: "50m"
  1. 安装并启动
  2. ```bash
  3. /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依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-data-mongodb</artifactId>
  8. </dependency>

Spring application配置

application.properties

  1. spring.data.mongodb.username=root
  2. spring.data.mongodb.password=example
  3. spring.data.mongodb.database=admin

测试能否正常启动

host:localhost port:27017 database:admin user:root password:example

项目结构

image.png

创建Domain Object

  1. package com.example.mongodb.model;
  2. import org.springframework.data.annotation.Id;
  3. import org.springframework.data.mongodb.core.index.Indexed;
  4. import org.springframework.data.mongodb.core.mapping.Document;
  5. import java.util.List;
  6. @Document("Department")
  7. public class Department {
  8. @Id
  9. private String id;
  10. @Indexed(name = "deptName")
  11. private String name;
  12. private String description;
  13. @DBRef
  14. private List<Employee> employees;
  15. //...getter setter
  16. }
  1. package com.example.mongodb.model;
  2. import org.springframework.data.annotation.Id;
  3. import org.springframework.data.mongodb.core.mapping.Document;
  4. @Document("Employee")
  5. public class Employee {
  6. @Id
  7. private String empId;
  8. private String name;
  9. private int age;
  10. private double salary;
  11. //...getter setter
  12. }

@Document 标识了要持久化到mongodb的DO。
@Id 文档的唯一标识,在mongodb中是objectId。
@DbRef 关联另一个Document对象,存入的是文档的引用,如果不使用这个注解,存入的是内容。不过即使使用@DbRef,mongodb本身并不维护关联数据,也就是说需要手动将数据插入到被关联文档。

两种操作数据的方式

MongoRepository


  1. package com.example.mongodb.repository;
  2. import com.example.mongodb.model.Department;
  3. import org.springframework.data.mongodb.repository.MongoRepository;
  4. import org.springframework.data.mongodb.repository.Query;
  5. import org.springframework.stereotype.Repository;
  6. import java.util.List;
  7. @Repository
  8. public interface DepartmentRepository extends MongoRepository<Department,String> {
  9. @Query(value = "{'Employee.name': ?0}", fields = "{'employees' : 0}")
  10. Department findDepartmentByEmployeeName(String empName);
  11. List<Department> findDepartmentByName(String name);
  12. }

MongoTemplate

  1. package com.example.mongodb.repository;
  2. import com.example.mongodb.model.Department;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.data.mongodb.core.MongoTemplate;
  5. import org.springframework.data.mongodb.core.query.Criteria;
  6. import org.springframework.data.mongodb.core.query.Query;
  7. import org.springframework.data.mongodb.core.query.Update;
  8. import org.springframework.stereotype.Repository;
  9. import java.util.List;
  10. @Repository
  11. public class DeptRepository {
  12. @Autowired
  13. private MongoTemplate mongoTemplate;
  14. public List<Department> findAll() {
  15. return mongoTemplate.findAll(Department.class);
  16. }
  17. public List<Department> findDepartmentByName(String deptName){
  18. Query query = new Query();
  19. query.addCriteria(Criteria.where("name").is(deptName));
  20. return mongoTemplate.find(query, Department.class);
  21. }
  22. public Department save(Department department) {
  23. mongoTemplate.save(department);
  24. return department;
  25. }
  26. public Department update(Department department){
  27. Query query = new Query();
  28. query.addCriteria(Criteria.where("id").is(department.getId()));
  29. Update update = new Update();
  30. update.set("name", department.getName());
  31. update.set("description", department.getDescription());
  32. return mongoTemplate.findAndModify(query, update, Department.class);
  33. }
  34. public void deleteById(String deptId) {
  35. Query query = new Query();
  36. query.addCriteria(Criteria.where("id").is(deptId));
  37. mongoTemplate.remove(query, Department.class);
  38. }
  39. }

创建Controller

  1. package com.example.mongodb.controller;
  2. import com.example.mongodb.model.Department;
  3. import com.example.mongodb.model.Employee;
  4. import com.example.mongodb.repository.DepartmentRepository;
  5. import com.example.mongodb.repository.DeptRepository;
  6. import com.example.mongodb.repository.EmpRepository;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.web.bind.annotation.*;
  9. import java.util.Collections;
  10. import java.util.List;
  11. import java.util.Optional;
  12. @RestController
  13. public class DepartmentController {
  14. @Autowired
  15. DepartmentRepository departmentRepository;
  16. @Autowired
  17. DeptRepository deptRepository;
  18. @Autowired
  19. EmpRepository empRepository;
  20. @PostMapping("/v1/dept/s")
  21. public Department v1save(@RequestBody Department department) {
  22. List<Employee> employees = Optional.ofNullable(department.getEmployees()).orElse(Collections.emptyList());
  23. employees.forEach(employee -> empRepository.save(employee));
  24. return departmentRepository.save(department);
  25. }
  26. @GetMapping("/v1/dept/l")
  27. public List<Department> v1list(){
  28. return departmentRepository.findAll();
  29. }
  30. @PutMapping("/v1/dept/u/{deptId}")
  31. public Department v1update(@RequestBody Department department, @PathVariable String deptId) {
  32. department.setId(deptId);
  33. List<Employee> employees = Optional.ofNullable(department.getEmployees()).orElse(Collections.emptyList());
  34. employees.forEach(employee -> empRepository.save(employee));
  35. return departmentRepository.save(department);
  36. }
  37. @DeleteMapping("/v1/dept/d/{deptId}")
  38. public String v1delete(@PathVariable String deptId) {
  39. departmentRepository.deleteById(deptId);
  40. return deptId;
  41. }
  42. @GetMapping("/v1/dept/get/{deptName}")
  43. public List<Department> v1getByName(@PathVariable String deptName) {
  44. return departmentRepository.findDepartmentByName(deptName);
  45. }
  46. @GetMapping("/v1/dept/get/emp/{empName}")
  47. public Department v1getByEmpName(@PathVariable String empName) {
  48. return departmentRepository.findDepartmentByEmployeeName(empName);
  49. }
  50. @PostMapping("/v2/dept/s")
  51. public Department v2save(Department department) {
  52. List<Employee> employees = Optional.ofNullable(department.getEmployees()).orElse(Collections.emptyList());
  53. employees.forEach(employee -> empRepository.save(employee));
  54. return deptRepository.save(department);
  55. }
  56. @GetMapping("/v2/dept/l")
  57. public List<Department> v2list() {
  58. return deptRepository.findAll();
  59. }
  60. @PutMapping("/v2/dept/u")
  61. public Department v2update(Department department){
  62. List<Employee> employees = Optional.ofNullable(department.getEmployees()).orElse(Collections.emptyList());
  63. employees.forEach(employee -> empRepository.save(employee));
  64. return deptRepository.update(department);
  65. }
  66. @DeleteMapping("/v2/dept/d/{deptId}")
  67. public void v2delete(@PathVariable String deptId) {
  68. deptRepository.deleteById(deptId);
  69. }
  70. @GetMapping("/v2/dept/get/{deptName}")
  71. public List<Department> v2getByName(@PathVariable String deptName){
  72. return deptRepository.findDepartmentByName(deptName);
  73. }
  74. }

v1的接口使用MongoRepository方式操作数据,v2的接口使用MonoTemplate方式操作数据。

测试

  1. ###新增
  2. POST http://localhost:8080/v1/dept/s
  3. Content-Type: application/json
  4. {
  5. "id": "10010",
  6. "name": "中国联通",
  7. "description": "中国联通",
  8. "employees": [
  9. {
  10. "empId": "1",
  11. "name": "jack ma",
  12. "age": 78,
  13. "salary": 900000.0
  14. }
  15. ]
  16. }
  17. ###更新
  18. PUT http://localhost:8080/v1/dept/u/10010
  19. Content-Type: application/json
  20. {
  21. "id": "10010",
  22. "name": "中国联通",
  23. "description": "中国联通",
  24. "employees": [
  25. {
  26. "empId": "1",
  27. "name": "jack ma",
  28. "age": 78,
  29. "salary": 900000.0
  30. },
  31. {
  32. "empId": "2",
  33. "name": "pony ma",
  34. "age": 78,
  35. "salary": 900000.0
  36. }
  37. ]
  38. }
  39. ###删除
  40. DELETE http://localhost:8080/v1/dept/d/10010
  41. ###查询
  42. GET http://localhost:8080/v1/dept/l

image.png
image.png

项目地址