Spring boot整合Mybatis实现级联一对多CRUD操作的完整步骤

下面是“Spring boot整合Mybatis实现级联一对多CRUD操作的完整步骤”的攻略。

一、准备工作

首先,需要搭建好Spring Boot项目,并将Mybatis集成到项目中。可以参考官方文档。然后,需要确保数据库中有两张表,一张父表和一张子表。例如,下面是一个父表和一个子表的示例:

父表 student:

| id | name |

| ---- | ---- |

| 1 | 张三 |

| 2 | 李四 |

子表 course:

| id | name | student_id |

| ---- | ------ | ---------- |

| 1 | 语文 | 1 |

| 2 | 数学 | 1 |

| 3 | 英语 | 2 |

二、建立实体类

在父表和子表对应的包中,建立两个实体类 Student 和 Course。实体类中需要使用注解来定义表名和字段名,例如:

Student.java:

public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Transient
    private List<Course> courses;

    // getter/setter 省略
}

Course.java:

public class Course {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Column(name = "student_id")
    private Long studentId;

    // getter/setter 省略
}

这里使用了注解 @Id 和 @GeneratedValue 来定义主键和自动增长策略。同时,使用了 @Column 注解来定义字段名,因为在实际数据库表中,字段名可能跟变量名不一致。

注意到 Student 实体类中还定义了一个 courses 属性,该属性用于存储所有和该学生相关的课程对象,因为该示例中实现的是一对多关系。

三、建立Mapper接口

接下来,建立父表和子表对应的 Mapper 接口。例如,Mapper.java 中定义如下:

StudentMapper.java:

public interface StudentMapper {

    List<Student> selectAll();

    Student selectById(Long id);

    void insert(Student student);

    void update(Student student);

    void delete(Long id);

    List<Course> selectCoursesByStudentId(Long studentId);

    void insertCourse(Course course);

    void updateCourse(Course course);

    void deleteCourse(Long id);
}

CourseMapper.java:

public interface CourseMapper {

    List<Course> selectAll();

    Course selectById(Long id);

    void insert(Course course);

    void update(Course course);

    void delete(Long id);
}

需要注意的是,StudentMapper 中包含了一个 selectCoursesByStudentId 方法,用于根据学生 ID 查询该学生所有的课程列表。同时,StudentMapper 中还包含了 insertCourse、updateCourse 和 deleteCourse 方法,用于分别新增、修改和删除学生的课程。

四、建立Mapper XML文件

在resources目录下建立一个mapper目录,然后分别在其中建立“StudentMapper.xml”和“CourseMapper.xml”两个XML文件。

StudentMapper.xml:

<mapper namespace="com.example.mapper.StudentMapper">
    <select id="selectAll" resultType="Student">
        select * from student
    </select>
    <select id="selectById" resultType="Student">
        select * from student where id = #{id}
    </select>
    <insert id="insert" useGeneratedKeys="true" keyProperty="id" parameterType="Student">
        insert into student (name) values (#{name})
    </insert>
    <update id="update" parameterType="Student">
        update student set name = #{name} where id = #{id}
    </update>
    <delete id="delete" parameterType="Long">
        delete from student where id = #{id}
    </delete>
    <select id="selectCoursesByStudentId" resultMap="courseResultMap">
        select * from course where student_id = #{studentId}
    </select>
    <insert id="insertCourse" parameterType="Course">
        insert into course (name, student_id) values (#{name}, #{studentId})
    </insert>
    <update id="updateCourse" parameterType="Course">
        update course set name = #{name} where id = #{id}
    </update>
    <delete id="deleteCourse" parameterType="Long">
        delete from course where id = #{id}
    </delete>

    <resultMap id="courseResultMap" type="Course">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="studentId" column="student_id"/>
    </resultMap>

    <resultMap id="studentResultMap" type="Student">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <collection property="courses" ofType="Course" resultMap="courseResultMap"/>
    </resultMap>
</mapper>

CourseMapper.xml:

<mapper namespace="com.example.mapper.CourseMapper">
    <select id="selectAll" resultType="Course">
        select * from course
    </select>
    <select id="selectById" resultType="Course">
        select * from course where id = #{id}
    </select>
    <insert id="insert" useGeneratedKeys="true" keyProperty="id" parameterType="Course">
        insert into course (name, student_id) values (#{name}, #{studentId})
    </insert>
    <update id="update" parameterType="Course">
        update course set name = #{name} where id = #{id}
    </update>
    <delete id="delete" parameterType="Long">
        delete from course where id = #{id}
    </delete>
</mapper>

其中,StudentMapper.xml 中定义了一个 courseResultMap 和 studentResultMap 两个 resultMap,用于将结果集映射成对应的实体类。

五、建立Service层

在 service 包下建立两个 Service 接口和实现类,对应 Student 和 Course 实体类。

例如,StudentServiceImpl.java 中定义如下:

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private CourseMapper courseMapper;

    @Override
    public List<Student> selectAll() {
        List<Student> students = studentMapper.selectAll();
        for (Student student : students) {
            List<Course> courses = courseMapper.selectCoursesByStudentId(student.getId());
            student.setCourses(courses);
        }
        return students;
    }

    @Override
    public Student selectById(Long id) {
        Student student = studentMapper.selectById(id);
        if (student != null) {
            List<Course> courses = courseMapper.selectCoursesByStudentId(student.getId());
            student.setCourses(courses);
        }
        return student;
    }

    @Override
    @Transactional
    public void insert(Student student) {
        studentMapper.insert(student);
        List<Course> courses = student.getCourses();
        if (courses != null) {
            for (Course course : courses) {
                course.setStudentId(student.getId());
                courseMapper.insert(course);
            }
        }
    }

    @Override
    @Transactional
    public void update(Student student) {
        studentMapper.update(student);
        List<Course> oldCourses = courseMapper.selectCoursesByStudentId(student.getId());
        List<Course> newCourses = student.getCourses();
        if (newCourses == null) {
            newCourses = new ArrayList<>();
        }
        for (Course oldCourse : oldCourses) {
            boolean exist = false;
            for (Course newCourse : newCourses) {
                if (newCourse.getId() != null && newCourse.getId().equals(oldCourse.getId())) {
                    exist = true;
                    courseMapper.update(newCourse);
                    break;
                }
            }
            if (!exist) {
                courseMapper.delete(oldCourse.getId());
            }
        }
        for (Course newCourse : newCourses) {
            if (newCourse.getId() == null) {
                newCourse.setStudentId(student.getId());
                courseMapper.insert(newCourse);
            }
        }
    }

    @Override
    public void delete(Long id) {
        studentMapper.delete(id);
        courseMapper.selectCoursesByStudentId(id).forEach(course -> courseMapper.delete(course.getId()));
    }

    @Override
    public void insertCourse(Course course) {
        courseMapper.insert(course);
    }

    @Override
    public void updateCourse(Course course) {
        courseMapper.update(course);
    }

    @Override
    public void deleteCourse(Long id) {
        courseMapper.delete(id);
    }
}

实现类中重写了各自的方法,例如 selectAll() 方法中,先查询出所有学生,然后再循环查询每个学生的课程列表,赋值给学生对象的 courses 属性。

六、建立Controller层

最后,在 controller 包下建立对应的 Controller 类。例如,StudentController.java 中定义如下:

@RestController
@RequestMapping("/students")
public class StudentController {

    @Autowired
    private StudentService studentService;

    @GetMapping
    public List<Student> selectAll() {
        return studentService.selectAll();
    }

    @GetMapping("/{id}")
    public Student selectById(@PathVariable Long id) {
        return studentService.selectById(id);
    }

    @PostMapping
    public void insert(@RequestBody Student student) {
        studentService.insert(student);
    }

    @PutMapping
    public void update(@RequestBody Student student) {
        studentService.update(student);
    }

    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id) {
        studentService.delete(id);
    }
}

在 Controller 类中,各个方法分别调用对应的 Service 方法来实现 CRUD 操作。

七、测试效果

完成以上全部步骤后,运行项目,可以使用 Postman 或其他工具进行测试。例如,使用 GET 请求 http://localhost:8080/students 可以查询出所有学生和他们的课程列表。

[
    {
        "id": 1,
        "name": "张三",
        "courses": [
            {
                "id": 1,
                "name": "语文",
                "studentId": 1
            },
            {
                "id": 2,
                "name": "数学",
                "studentId": 1
            }
        ]
    },
    {
        "id": 2,
        "name": "李四",
        "courses": [
            {
                "id": 3,
                "name": "英语",
                "studentId": 2
            }
        ]
    }
]

可以使用其他 HTTP 方法来执行增、删、改操作。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring boot整合Mybatis实现级联一对多CRUD操作的完整步骤 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • java == 引发的线上异常详解

    让我来详细讲解一下“java == 引发的线上异常详解”。 概述 在Java开发中,我们通常会使用“==”来比较两个对象是否相等。但是,如果使用不当,就可能会引发线上异常。本文将会详细探讨在Java中使用“==”可能会遇到的问题,以及如何避免这些问题。 引发异常的问题 基本类型与包装类比较 在Java中,基本类型和其对应的包装类是不同的类型,它们互相之间并不…

    Java 2023年5月27日
    00
  • java反射的一些理解

    首先简单介绍下java反射的应用场景:java反射多用于框架设计中。 其次,简述下框架:可重复用的,用来提高编程效率的代码。一些重复性的工作不需要在去开发,直接利用框架集成起来,用的时候调用框架,传递参数等等。 再次,介绍下java反射获取类对象的三种方式: Class.forName(“全限定类名”):这种用的最常见,也最符合反射的理念,参数可以是字符串,…

    Java 2023年4月22日
    00
  • 高并发场景下的 HttpClient 优化,QPS 大大提升!

    HttpClient优化思路: 池化 长连接 httpclient和httpget复用 合理的配置参数(最大并发请求数,各种超时时间,重试次数) 异步 6、多读源码 1.背景 我们有个业务,会调用其他部门提供的一个基于http的服务,日调用量在千万级别。使用了httpclient来完成业务。之前因为qps上不去,就看了一下业务代码,并做了一些优化,记录在这里…

    Java 2023年5月8日
    00
  • Java利用jenkins做项目的自动化部署

    下面是关于“Java利用Jenkins做项目的自动化部署”的完整攻略: 简介 Jenkins是一个开源的自动化部署工具,用于构建、测试、发布软件项目。Java开发人员可以使用Jenkins实现自己的自动化部署。Java利用Jenkins做项目的自动化部署,主要分为两个步骤: 安装Jenkins 配置Jenkins、部署项目 接下来将针对这两个方面分别详细介绍…

    Java 2023年5月19日
    00
  • java实现字符串匹配求两个字符串的最大公共子串

    Java实现字符串匹配求两个字符串的最大公共子串可以通过以下步骤来实现: 首先,我们需要定义两个字符串用于匹配,并创建一个函数或方法来解决此问题。 示例代码: public static String longestCommonSubstring(String s1, String s2) { int len1 = s1.length(), len2 = s…

    Java 2023年5月19日
    00
  • Java基于Dijkstra算法实现校园导游程序

    Java基于Dijkstra算法实现校园导游程序攻略 1. 确定算法 首先,我们需要确定使用什么算法来实现校园导游程序,此处我们选择使用Dijkstra算法。 Dijkstra算法是一种用于带权图的单源最短路径算法,可以帮助我们找到两点之间的最短路径。在本程序中,我们需要将所有景点看作节点,将各个景点之间的距离看作边权,应用Dijkstra算法求解距离最短的…

    Java 2023年5月19日
    00
  • Java中的ArrayList是什么?

    Java中的ArrayList是一种基于动态数组实现的集合类,它能够存储对象,并且可以根据需要动态扩展容量大小,具有快速的随机访问能力。本文将对Java中的ArrayList进行详细讲解,包括其定义、操作、特性和示例说明。 ArrayList的定义 ArrayList是Java中提供的一种集合类,它是基于动态数组实现的,能够存储对象,并且可以根据需要动态扩展…

    Java 2023年4月27日
    00
  • 详解SpringBoot和Mybatis配置多数据源

    下面详细讲解一下关于“详解SpringBoot和Mybatis配置多数据源”的完整攻略。 一、为什么需要配置多数据源? 在实际的项目中,我们很有可能需要同时访问多个数据库,而这些数据库可能是不同类型的,比如 MySQL 和 Redis,因此需要在 Spring Boot 和 Mybatis 的框架基础上实现多数据源配置。 二、配置过程 首先,在 pom.xm…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部