第十六节:SpringBoot使用JPA一对多,多对多访问数据库

举一个例子来说明这个多对对的关系。

我们在选课过程中,一个学生可以选多门课。反过来一个课程会被多个人选。两边都会存在多对多的关系。

image-20211223115332391

在JPA中就可以用@ManyToMany去解决,具体如下

pom.xml关键依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-jpa</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>mysql</groupId>
  7. <artifactId>mysql-connector-java</artifactId>
  8. <scope>runtime</scope>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.projectlombok</groupId>
  12. <artifactId>lombok</artifactId>
  13. <optional>true</optional>
  14. </dependency>

3个实体类

学生表Student

  1. package com.rumenz.lession16.controller.entity;
  2. import lombok.Getter;
  3. import lombok.Setter;
  4. import javax.persistence.*;
  5. import java.util.Set;
  6. /**
  7. * @className: Student
  8. * @description: TODO 类描述
  9. * @author: 入门小站 rumenz.com
  10. * @date: 2021/12/15
  11. **/
  12. @Getter
  13. @Setter
  14. @Entity
  15. @Table(name="student")
  16. public class Student {
  17. @Id
  18. @GeneratedValue(strategy = GenerationType.IDENTITY)
  19. private Integer id;
  20. private String name;
  21. @ManyToMany
  22. @JoinTable(
  23. name = "student_course",
  24. joinColumns = @JoinColumn(name = "sid"),
  25. inverseJoinColumns = @JoinColumn(name = "cid"))
  26. Set<Course> likedCourses;
  27. }
  • @ManyToMany标注存在对对多的关系
  • @JoinTable定义数据库关系,joinColumns属性链接自己,inverseJoinColumns属性链接对方
  • @JoinColumn注解定义外键

在使用@ManyToMany注解的时候,在输出实体类时,出现了java.lang.StackOverflowError报错,这个是因为在实体类中,使用了@Data注解,@Data注解中的@ToString会导致java.lang.StackOverflowError,需要重写

不能用lombok的@EqualsAndHashCode和@ToString,否则死循环内存溢出

课程表Course

  1. package com.rumenz.lession16.controller.entity;
  2. import com.fasterxml.jackson.annotation.JsonIgnore;
  3. import lombok.*;
  4. import javax.persistence.*;
  5. import java.util.Set;
  6. /**
  7. * @className: Course
  8. * @description: TODO 类描述
  9. * @author: 入门小站 rumenz.com
  10. * @date: 2021/12/15
  11. **/
  12. @Getter
  13. @Setter
  14. @Entity
  15. @Table(name="course")
  16. public class Course {
  17. @Id
  18. @GeneratedValue(strategy = GenerationType.IDENTITY)
  19. private Integer id;
  20. private String name;
  21. @JsonIgnore
  22. @ManyToMany(mappedBy = "likedCourses")
  23. Set<Student> likes;
  24. }

关系表StudentCourse

  1. package com.rumenz.lession16.controller.entity;
  2. import lombok.Data;
  3. import javax.persistence.*;
  4. /**
  5. * @className: StudentCourse
  6. * @description: TODO 类描述
  7. * @author: 入门小站 rumenz.com
  8. * @date: 2021/12/15
  9. **/
  10. @Data
  11. @Entity
  12. @Table(name="student_course")
  13. public class StudentCourse {
  14. @Id
  15. @GeneratedValue(strategy = GenerationType.IDENTITY)
  16. private Integer id;
  17. private Integer sid;
  18. private Integer cid;
  19. private String rating;
  20. }

repository

数据库访问的ORM,也叫持久层,负责访问数据库。一般通过继承JpaRepository,CurdRepository实现,这里声明的接口不必实现,只要遵循Jpa规范就可以自动生成。

StudentRepository

  1. package com.rumenz.lession16.controller.repository;
  2. import com.rumenz.lession16.controller.entity.Student;
  3. import org.springframework.data.repository.CrudRepository;
  4. import org.springframework.stereotype.Repository;
  5. /**
  6. * @className: StudentRepository
  7. * @description: TODO 类描述
  8. * @author: 入门小站 rumenz.com
  9. * @date: 2021/12/15
  10. **/
  11. @Repository
  12. public interface StudentRepository extends CrudRepository<Student,Integer> {
  13. }

CourseRepository

  1. package com.rumenz.lession16.controller.repository;
  2. import com.rumenz.lession16.controller.entity.Course;
  3. import org.springframework.data.repository.CrudRepository;
  4. import org.springframework.stereotype.Repository;
  5. /**
  6. * @className: CourseRepository
  7. * @description: TODO 类描述
  8. * @author: 入门小站 rumenz.com
  9. * @date: 2021/12/15
  10. **/
  11. @Repository
  12. public interface CourseRepository extends CrudRepository<Course,Integer> {
  13. }

StudentCourseRepository

  1. package com.rumenz.lession16.controller.repository;
  2. import com.rumenz.lession16.controller.entity.StudentCourse;
  3. import org.springframework.data.repository.CrudRepository;
  4. import org.springframework.stereotype.Repository;
  5. /**
  6. * @className: StudentCourseRepository
  7. * @description: TODO 类描述
  8. * @author: 入门小站 rumenz.com
  9. * @date: 2021/12/15
  10. **/
  11. @Repository
  12. public interface StudentCourseRepository extends CrudRepository<StudentCourse,Integer> {
  13. }

service

业务层,负责调用Repository返回,处理数据

UserService

  1. package com.rumenz.lession16.controller.service;
  2. import com.rumenz.lession16.controller.entity.Student;
  3. import java.util.List;
  4. /**
  5. * @className: UserService
  6. * @description: TODO 类描述
  7. * @author: 入门小站 rumenz.com
  8. * @date: 2021/12/15
  9. **/
  10. public interface UserService {
  11. List<Student> listStudent();
  12. }

UserServiceImpl

UserService接口的实现类

  1. package com.rumenz.lession16.controller.service.Impl;
  2. import com.rumenz.lession16.controller.entity.Student;
  3. import com.rumenz.lession16.controller.repository.StudentRepository;
  4. import com.rumenz.lession16.controller.service.UserService;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Service;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. /**
  10. * @className: UserServiceImpl
  11. * @description: TODO 类描述
  12. * @author: 入门小站 rumenz.com
  13. * @date: 2021/12/15
  14. **/
  15. @Service
  16. public class UserServiceImpl implements UserService {
  17. @Autowired
  18. StudentRepository studentRepository;
  19. @Override
  20. public List<Student> listStudent() {
  21. List<Student> list=new ArrayList<>();
  22. Iterable<Student> res = studentRepository.findAll();
  23. res.forEach(item->{
  24. System.out.println(item.getLikedCourses().toString());
  25. });
  26. res.forEach(list::add);
  27. return list;
  28. }
  29. }

Controller

控制器,负责接收前端请求,调用service返回数据。

RumenzController

  1. package com.rumenz.lession16.controller;
  2. import com.rumenz.lession16.controller.entity.Student;
  3. import com.rumenz.lession16.controller.service.UserService;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import java.util.List;
  9. /**
  10. * @className: RumenzController
  11. * @description: TODO 类描述
  12. * @author: 入门小站 rumenz.com
  13. * @date: 2021/12/15
  14. **/
  15. @RestController
  16. @RequestMapping("/rumenz")
  17. public class RumenzController {
  18. @Autowired
  19. UserService userService;
  20. //多对多查询
  21. @GetMapping("/listStudent")
  22. public List<Student> listStudent(){
  23. return userService.listStudent();
  24. }
  25. }

本小结源码地址:

介绍

  • 关注【入门小站】回复【1001】获取 linux常用命令速查手册
  • 关注【入门小站】回复【1003】获取 LeetCode题解【java语言实现】
  • 关注【入门小站】回复【1004】获取 Java基础核心总结
  • 关注【入门小站】回复【1009】获取 阿里巴巴Java开发手册
返回笔记列表
入门小站