环境信息

环境信息: OS:Win10 Jdk:JavaSE 8 Ide:Idea Ultimate Spring Boot:2.1.7.RELEASE

2.创建Web项目

Idea集成了Spring Initializr,新建项目:

  • 1.选择Spring Initializr

Spring Boot 2.x 中使用 H2数据库 - 图1

  • 2.填写基本信息
    Spring Boot 2.x 中使用 H2数据库 - 图2
  • 3.选择需要的工具
    选择WebSpring Data MongoDB等必要依赖:

Spring Boot 2.x 中使用 H2数据库 - 图3

  • 4.确认完成

忽略我的其他项目:
Spring Boot 2.x 中使用 H2数据库 - 图4

3.创建数据库&表

3.1 创建数据库

手动命令创建数据库studentService
Spring Boot 2.x 中使用 H2数据库 - 图5

3.2 创建数据表

右键数据库,打开Open Shell执行Js脚本:

  • 1.创建表
  1. var names = db.getCollectionNames();
  2. // -- Create Collections --
  3. if (!names.includes('students')) {
  4. db.createCollection("students", {});
  5. print("create collection students");
  6. }
  7. if (!names.includes('scores')) {
  8. db.createCollection("scores", {});
  9. print("create collection scores");
  10. }

Spring Boot 2.x 中使用 H2数据库 - 图6

  • 2.创建表索引
  1. // -- Create students indexes --
  2. var studentsIndexNames = db.userRoles.getIndexes().map(function (i) {
  3. return i.name
  4. });
  5. if (!studentsIndexNames.includes('unique_name_address')) {
  6. db.students.createIndex({
  7. "name": 1,
  8. "address": 1
  9. }, {
  10. name: "unique_name_address",
  11. background: true,
  12. unique: true
  13. });
  14. print('create students index unique_name_address');
  15. }
  16. // -- Create scores indexes --
  17. var scoresIndexNames = db.scores.getIndexes().map(function (i) {
  18. return i.name
  19. });
  20. if (!scoresIndexNames.includes('unique_studentId_subject')) {
  21. db.scores.createIndex({
  22. "studentId": 1,
  23. "subject": 1
  24. }, {
  25. name: "unique_studentId_subject",
  26. background: true,
  27. unique: true
  28. });
  29. print('create scores index unique_studentId_subject');
  30. }

Spring Boot 2.x 中使用 H2数据库 - 图7

3.3 插入初始化数据

  1. var studentsResult = db.students.findOne({"name": "Even"});
  2. if (studentsResult == null) {
  3. db.students.insert([ /* 1 */
  4. {
  5. "name" : "Even",
  6. "age" : 9.0,
  7. "sex" : "Male",
  8. "address" : "Xian",
  9. "hobbies" : [
  10. "YuWen",
  11. "English"
  12. ]
  13. },
  14. /* 2 */
  15. {
  16. "name" : "Weison",
  17. "age" : 10.0,
  18. "sex" : "Male",
  19. "address" : "Henan",
  20. "hobbies" : [
  21. "Wuli",
  22. "English"
  23. ]
  24. },
  25. /* 3 */
  26. {
  27. "name" : "Angule",
  28. "age" : 13,
  29. "sex" : "Female",
  30. "hobbies" : [
  31. "YuWen",
  32. "English"
  33. ],
  34. "address" : "Chengdu",
  35. "_class" : "com.wxx.sbm.domain.Student"
  36. }]);
  37. }
  38. var scoresResult = db.scores.findOne({"studentName": "Even"});
  39. if (scoresResult == null) {
  40. db.scores.insert([/* 1 */
  41. {
  42. "studentId" : "5d48dc820fd614486f1c1f09",
  43. "subject" : "YuWen",
  44. "studentName" : "Weison",
  45. "subjectScore" : 90
  46. },
  47. /* 2 */
  48. {
  49. "studentId" : "5d48dc820fd614486f1c1f09",
  50. "subject" : "English",
  51. "studentName" : "Weison",
  52. "subjectScore" : 98
  53. },
  54. /* 3 */
  55. {
  56. "studentId" : "5d48dc820fd614486f1c1f09",
  57. "subject" : "ShuXue",
  58. "studentName" : "Weison",
  59. "subjectScore" : 59
  60. },
  61. /* 4 */
  62. {
  63. "studentId" : "5d48dc820fd614486f1c1f08",
  64. "subject" : "YuWen",
  65. "studentName" : "Even",
  66. "subjectScore" : 90
  67. },
  68. /* 5 */
  69. {
  70. "studentId" : "5d48dc820fd614486f1c1f08",
  71. "subject" : "English",
  72. "studentName" : "Even",
  73. "subjectScore" : 98
  74. },
  75. /* 6 */
  76. {
  77. "studentId" : "5d48dc820fd614486f1c1f08",
  78. "subject" : "ShuXue",
  79. "studentName" : "Even",
  80. "subjectScore" : 59
  81. },
  82. /* 7 */
  83. {
  84. "studentId" : "5d48f09b4cf1451aad930f54",
  85. "subject" : "YuWen",
  86. "studentName" : "Angule",
  87. "subjectScore" : 90
  88. },
  89. /* 8 */
  90. {
  91. "studentId" : "5d48f09b4cf1451aad930f54",
  92. "subject" : "English",
  93. "studentName" : "Angule",
  94. "subjectScore" : 98
  95. },
  96. /* 9 */
  97. {
  98. "studentId" : "5d48f09b4cf1451aad930f54",
  99. "subject" : "ShuXue",
  100. "studentName" : "Angule",
  101. "subjectScore" : 59
  102. }]);
  103. }

预览数据:
Spring Boot 2.x 中使用 H2数据库 - 图8

4.集成Spring Data MongoDB

4.1 配置MongoDB链接信息

application-dev.yml

  1. spring:
  2. data:
  3. mongodb:
  4. database: studentService
  5. host: localhost
  6. port: 27017

4.2 创建Domain

Student:

  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. @Builder
  5. @Document(collection = "students")
  6. public class Student {
  7. @Id
  8. @JsonSerialize(using = ObjectIdSerializer.class)
  9. private ObjectId id;
  10. private String name;
  11. private Integer age;
  12. private String sex;
  13. private List<String> hobbies;
  14. private String address;
  15. }

Score:

  1. @Data
  2. @Builder
  3. @Document(collection = "scores")
  4. public class Score {
  5. @Id
  6. @JsonSerialize(using = ObjectIdSerializer.class)
  7. private ObjectId id;
  8. //学生编号
  9. @JsonSerialize(using = ObjectIdSerializer.class)
  10. private ObjectId studentId;
  11. private String studentName;
  12. //科目
  13. private String subject;
  14. //科目成绩
  15. private Integer subjectScore;
  16. }

StudentScore:

  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. @Builder
  5. public class StudentScore {
  6. private String name;
  7. private Integer age;
  8. private String sex;
  9. private Score score;
  10. }

StudentScores:

  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. @Builder
  5. public class StudentScores {
  6. private String name;
  7. private Integer age;
  8. private String sex;
  9. private List<Score> scoreList;
  10. }

4.3 创建StudentRepository

StudentRepository 继承自 CrudRepository,可以通过方法名映射来定义方法:

  1. public interface StudentRepository extends CrudRepository<Student, ObjectId> {
  2. public Student findStudentByName(String name);
  3. public Student findStudentByNameAndSex(String name, String sex);
  4. public Student findStudentByNameIn(List<String> name);
  5. public Integer deleteStudentByName(String name);
  6. }

方法名映射,参考:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation

4.4 创建CustomizedStudentRepository

当方法名映射无法满足需求的时候,可以自定义Repository,通过调用MongoTemplate的API来实现复杂查询、多表关联查询等:

  1. @Repository
  2. public class CustomizedStudentRepositoryImpl implements CustomizedStudentRepository {
  3. @Autowired
  4. private MongoTemplate mongoTemplate;
  5. @Override
  6. public StudentScore findStudentScoreByName(String name) {
  7. return null;
  8. }
  9. /**
  10. * 查找大于"10"岁 性别是"男" 并且 爱好"语文"和"英语"的 童鞋们
  11. *
  12. * @return
  13. */
  14. public List<Student> findStudentListByAgeAndSexAndHobbies() {
  15. Query query = query(where("age").gte(10)
  16. .and("sex").is("Male")
  17. .orOperator(where("hobbies").is("YuWen"),
  18. where("hobbies").is("English")));
  19. List<Student> students = mongoTemplate.find(query, Student.class, "students");
  20. return students;
  21. }
  22. /**
  23. * 查询所有童鞋和他们的各科成绩
  24. *
  25. * @return
  26. */
  27. public List<StudentScores> findStudentScoreList() {
  28. Aggregation aggregation = Aggregation.newAggregation(
  29. newLookup()
  30. .from("scores")
  31. .localField("name")
  32. .foreignField("studentName")
  33. .as("scores"),
  34. project()
  35. .andExpression("name").as("name")
  36. .andExpression("age").as("age")
  37. .andExpression("sex").as("sex")
  38. .andExpression("scores").as("scoreList"));
  39. AggregationResults<StudentScores> aggregationResults = mongoTemplate.aggregate(aggregation, "students", StudentScores.class);
  40. List<StudentScores> studentScores = aggregationResults.getMappedResults();
  41. return studentScores;
  42. }
  43. /**
  44. * 查询大于"10岁" 喜欢"语文"或"英语" 的"男孩" 的 "英语"成绩
  45. *
  46. * @return
  47. */
  48. public List<StudentScore> findStudentScores() {
  49. Aggregation aggregation = Aggregation.newAggregation(
  50. newLookup()
  51. .from("scores")
  52. .localField("name")
  53. .foreignField("studentName")
  54. .as("scores"),
  55. match(where("age").gte(10)
  56. .and("sex").is("Male")
  57. //.and("scores.subjectScore").gt(60) 这里不生效
  58. .orOperator(where("hobbies").is("YuWen"), where("hobbies").is("English"))),
  59. project()
  60. .andExpression("name").as("name")
  61. .andExpression("age").as("age")
  62. .andExpression("sex").as("sex")
  63. .andExpression("scores").as("score"),
  64. unwind("score"),
  65. match(where("score.subject").is("English")));
  66. AggregationResults<StudentScore> aggregationResults = mongoTemplate.aggregate(aggregation, "students", StudentScore.class);
  67. List<StudentScore> studentScores = aggregationResults.getMappedResults();
  68. return studentScores;
  69. }
  70. }

定制化Repository,参考:https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.single-repository-behavior

4.5 创建Service

  1. @Service
  2. public class StudentService {
  3. @Autowired
  4. private StudentRepository studentRepository;
  5. @Autowired
  6. private CustomizedStudentRepository customizedStudentRepository;
  7. public Student addStudent(Student student) {
  8. return studentRepository.save(student);
  9. }
  10. public Integer deleteStudentByName(String name) {
  11. return studentRepository.deleteStudentByName(name);
  12. }
  13. public Student updateStudent(Student student) {
  14. Student studentByName = studentRepository.findStudentByName(student.getName());
  15. student.setId(studentByName.getId());
  16. Student saveStudent = studentRepository.save(student);
  17. return saveStudent;
  18. }
  19. public Student findStudentById(ObjectId id) {
  20. Optional<Student> studentOptional = studentRepository.findById(id);
  21. return studentOptional.orElseGet(Student::new);
  22. }
  23. public Student findStudentByNameAndSex(String name, String sex) {
  24. Student student = studentRepository.findStudentByNameAndSex(name, sex);
  25. return student;
  26. }
  27. public List<Student> findStudents() {
  28. List<Student> students = (List) studentRepository.findAll();
  29. return students;
  30. }
  31. public List<Student> findStudentsById(List<ObjectId> ids) {
  32. List<Student> students = (List) studentRepository.findAllById(ids);
  33. return students;
  34. }
  35. public List<Student> findStudentListByAgeAndSexAndHobbies() {
  36. List<Student> studentList = customizedStudentRepository.findStudentListByAgeAndSexAndHobbies();
  37. return studentList;
  38. }
  39. public List<StudentScores> findStudentScoreList() {
  40. List<StudentScores> studentScoreList = customizedStudentRepository.findStudentScoreList();
  41. return studentScoreList;
  42. }
  43. public List<StudentScore> findStudentScores() {
  44. List<StudentScore> studentScoreList = customizedStudentRepository.findStudentScores();
  45. return studentScoreList;
  46. }
  47. }

4.6 创建Controller

  1. @RestController
  2. public class StudentController {
  3. @Autowired
  4. private StudentService studentService;
  5. @GetMapping("/students")
  6. public List<Student> getStudentList() {
  7. List<Student> students = studentService.findStudents();
  8. return students;
  9. }
  10. @PostMapping("/students")
  11. public Student saveStudent(@RequestBody Student student) {
  12. Student addStudent = studentService.addStudent(student);
  13. return addStudent;
  14. }
  15. @DeleteMapping("/students/{name}")
  16. public Integer deleteStudentByName(@PathVariable String name) {
  17. Integer deleteNum = studentService.deleteStudentByName(name);
  18. return deleteNum;
  19. }
  20. @PutMapping("/students")
  21. public Student updateStudent(@RequestBody Student student) {
  22. Student updateStudent = studentService.updateStudent(student);
  23. return updateStudent;
  24. }
  25. @GetMapping("/students/list")
  26. public List<Student> getStudentListByAgeAndSexAndHobbies() {
  27. List<Student> studentList = studentService.findStudentListByAgeAndSexAndHobbies();
  28. return studentList;
  29. }
  30. @GetMapping("/students/scores")
  31. public List<StudentScores> getStudentScoresList() {
  32. List<StudentScores> studentList = studentService.findStudentScoreList();
  33. return studentList;
  34. }
  35. @GetMapping("/students/score")
  36. public List<StudentScore> getStudentScoreList() {
  37. List<StudentScore> studentScores = studentService.findStudentScores();
  38. return studentScores;
  39. }
  40. }

两个比较复杂的接口返回:
/students/scores
Spring Boot 2.x 中使用 H2数据库 - 图9

/students/score
Spring Boot 2.x 中使用 H2数据库 - 图10

代码 —> https://github.com/WeisonWei/springboot-aggregation/tree/master/springboot-mvc-mongodb