下面是“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技术站