SpringBoot2.x与MongoDB集成(十)

2020-05-18 18:15:04 浏览数 (1)

准备工作

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

要操作的集合示例数据结构(即model)

Department: String id String name String description Array employees Employee: String empId String name int age double salary one to many relationships

安装MongoDB

  • MongoDB快速入门指南与docker-compose快体验
  • https://www.yuque.com/ekko/database/dkluyg

创建Spring Boot项目

  • SpringBoot2.x快速入门指南(一)
  • https://www.yuque.com/ekko/spring/qqt7xd

添加Mongo依赖

代码语言:javascript复制
<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

代码语言:javascript复制
spring.data.mongodb.username=root
spring.data.mongodb.password=example
spring.data.mongodb.database=admin

测试能否正常启动

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

项目结构

创建Domain Object

代码语言:javascript复制
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 {
    @Id
    private String id;
    @Indexed(name = "deptName")
    private String name;
    private String description;

    @DBRef
    private List<Employee> employees;
    //...getter setter
}
代码语言:javascript复制
package com.example.mongodb.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document("Employee")
public class Employee {

    @Id
    private String empId;
    private String name;
    private int age;
    private double salary;
    //...getter setter
}

@Document 标识了要持久化到mongodb的DO。

@Id 文档的唯一标识,在mongodb中是objectId。

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

两种操作数据的方式

MongoRepository

代码语言:javascript复制
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;

@Repository
public interface DepartmentRepository extends MongoRepository<Department,String> {
    @Query(value = "{'Employee.name': ?0}", fields = "{'employees' : 0}")
    Department findDepartmentByEmployeeName(String empName);

    List<Department> findDepartmentByName(String name);
}

MongoTemplate

代码语言:javascript复制
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;

@Repository
public class DeptRepository {

    @Autowired
    private 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

代码语言:javascript复制
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;

@RestController
public class DepartmentController {
    @Autowired
    DepartmentRepository departmentRepository;
    @Autowired
    DeptRepository deptRepository;
    @Autowired
    EmpRepository 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方式操作数据。

测试

代码语言:javascript复制
###新增
POST http://localhost:8080/v1/dept/s
Content-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/10010
Content-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

项目地址

持续更新地址:https://www.yuque.com/ekko/spring/yxs4nf

>> 作者: rainbow unicorn

0 人点赞