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

yizhihongxing

下面是“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实现科学计算器的完整过程,涵盖了设计、实现和测试。 设计 在设计科学计算器之前,我们需要先了解需求和功能。在这里,我们将实现一款基本的科学计算器,包括以下功能: 加、减、乘、除 平方、开方 对数、三角函数 常量π和e 接下来,我们将对应的功能拆分为模块,然后设计相应的类和方法。 功能模块 加减…

    Java 2023年5月18日
    00
  • springboot 整合邮件发送功能

    整合邮件发送功能是 Spring Boot 中常见的应用场景之一。下面是整合邮件发送功能的完整攻略: 步骤一:添加邮件依赖 在 pom.xml 文件中添加以下依赖,在这个依赖中包含了spring-boot-starter-mail的所有依赖。 <dependency> <groupId>org.springframework.boot…

    Java 2023年6月15日
    00
  • 面试题快慢链表和快慢指针

    快慢链表和快慢指针是算法中常见的一种技巧。它们在链表中查找中间节点、判断链表是否有环等情况下十分实用。下面就对快慢链表和快慢指针的使用进行详细讲解。 快慢指针 快慢指针的基本思想是将两个指针指向链表的头节点,快指针每次走两步,慢指针每次走一步,当快指针走到链表的末尾时,慢指针指向的就是链表的中间节点。 示例 1: 找到链表的中间节点 我们有一个链表,包含以下…

    Java 2023年5月19日
    00
  • 基于SpringBoot项目遇到的坑–Date入参问题

    让我来详细讲解一下 “基于SpringBoot项目遇到的坑–Date入参问题” 的完整攻略。 背景 在进行 SpringBoot 开发过程中,我们经常会遇到 Date 入参的问题。比如从前端传递 Date 类型参数或者从数据库中查询出 Date 类型数据时,我们需要使用 Date 进行传递和处理。但是在具体的实现过程中,可能会遇到一些问题,比如格式不正确,…

    Java 2023年6月1日
    00
  • JSP 前端数据本地排序实例代码

    当我们需要对表格数据进行排序时,我们可以使用前端的JavaScript进行排序。下面是一个使用JSP和JavaScript实现前端数据本地排序的示例代码: 首先,我们可以创建一个包含表格的HTML代码,表格中的每行数据都由一个对象构成。对象中的每个属性对应每一列的数据,例如姓名、身高、年龄等。 <table id="myTable"…

    Java 2023年6月15日
    00
  • JAVA十大排序算法之归并排序详解

    JAVA十大排序算法之归并排序详解 一、概述 归并排序是一种高效稳定的排序算法,它将待排序的序列分成若干个子序列,每个子序列都是有序的,然后再将有序的子序列合并成整体有序的序列。由于归并排序是基于比较的排序算法,因此时间复杂度为 O(nlogn)。 二、算法流程 归并排序算法分为两个过程:分治和合并。 分治:将待排序的序列平分成两个子序列,对左右两个子序列分…

    Java 2023年5月26日
    00
  • 实例讲解Java的MyBatis框架对MySQL中数据的关联查询

    下面是关于“实例讲解Java的MyBatis框架对MySQL中数据的关联查询”的完整攻略,内容如下: 1. 什么是MyBatis框架? MyBatis(又称ibatis)是一款优秀的基于Java语言的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的JDBC代码以及对结果集的封装,支持 JDBC事务处理和灵活的缓存机制。…

    Java 2023年5月20日
    00
  • 详解java创建一个女朋友类(对象啥的new一个就是)==建造者模式,一键重写

    让我详细解释一下如何使用建造者模式创建一个女朋友类。 建造者模式 建造者模式是一种创建型设计模式,通过一步一步构建复杂对象,最终形成一个完整的对象。在使用建造者模式时,我们可以将对象的构建过程抽象出来,通过不同的特定构建器组合这些步骤来构造出最终的对象。 创建女朋友类 下面就来创建一个女朋友类吧!首先,我们要定义一个Girlfriend类,它包含一些属性,例…

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