Mybatis中使用collection进行多对多双向关联示例(含XML版与注解版)

XML版本:

实体类:

@Data
@NoArgsConstructor
public class Course {
protected Integer id;
protected String name;
protected List<Student> students = new ArrayList<Student>(); public Course(Integer id) {
this.id = id;
} public Course(String name) {
this.name = name;
} public String toLazyString() {
return "Course:{id: " + this.id + "; name: " + this.name + "}";
} }
@Data
@ToString
@NoArgsConstructor
public class Student {
protected Integer id;
protected String name;
protected List<Course> courses = new ArrayList<Course>(); public Student(Integer id) {
this.id = id;
} public Student(String name) {
this.name = name;
} public String toLazyString() {
return "Student:{id: " + this.id + " ; name: " + this.name + "}";
}
}
@Data
@ToString
@NoArgsConstructor
public class StudentCourse {
private Integer studentId;
private Integer courseId;
private Integer score; public StudentCourse(Integer studentId, Integer courseId) {
this.studentId = studentId;
this.courseId = courseId;
} public StudentCourse(Integer score) {
this.score = score;
}
}
@Data
@ToString
public class StudentExt extends Student {
private String courseName;
private String courseScore;
}

Mapper接口:

public interface CourseMapper {
public Course selectById(Integer id); public int insertCourse(Course course); public int updateCourse(Course course); public int deleteCourse(Course course);
}
public interface StudentMapper {
public Student selectById(Integer id);
public int insertStudent(Student employee);
public int updateStudent(Student employee);
public int deleteStudent(Student employee);
public List<Student> selectStudentByCourseAndScore(@Param("course") Course course,
@Param("studentCourse") StudentCourse studentCourse);
}
public interface StudentCourseMapper {
public int insertStudentCourse(@Param("student") Student student, @Param("course") Course course);
public int deleteStudentCourse(@Param("student") Student student, @Param("course") Course course);
public int deleteStudentCourseByStudent(@Param("student") Student student);
}

Mapper映射文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.sunwii.mybatis.mapper.CourseMapper">
<resultMap type="Course" id="CourseMap_basic">
<id property="id" column="cid" />
<result property="name" column="name" />
</resultMap>
<resultMap type="Course" id="CourseMap" extends="CourseMap_basic">
<!-- 多对多关联:使用select引用方式 -->
<collection property="students" column="cid" ofType="Student" select="com.sunwii.mybatis.mapper.StudentMapper.selectByCourse" fetchType="lazy">
</collection>
</resultMap> <select id="selectById" parameterType="Integer"
resultMap="CourseMap">
select id as cid, name from t_course c where c.id=#{id}
</select> <select id="selectByStudent" parameterType="Integer"
resultMap="CourseMap_basic">
select c.id as cid, c.name from t_course c inner join t_student_course sc
on c.id=sc.course_id and sc.student_id=#{studentId}
</select> <insert id="insertCourse" parameterType="Course" keyColumn="id"
keyProperty="id" useGeneratedKeys="true">
insert into t_course(name)
values(#{name})
</insert> <update id="updateCourse" parameterType="Course">
update t_course set
name=#{name}
where id=#{id}
</update> <delete id="deleteCourse" parameterType="Course">
delete from t_course
where
id=#{id}
</delete>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.sunwii.mybatis.mapper.StudentMapper">
<resultMap type="Student" id="StudentMap_basic">
<id property="id" column="sid" />
<result property="name" column="name" />
</resultMap>
<resultMap type="StudentExt" id="StudentMap_basic_ext" extends="StudentMap_basic">
<result property="courseName" column="cousename" />
<result property="courseScore" column="coursescore" />
</resultMap>
<resultMap type="Student" id="StudentMap" extends="StudentMap_basic">
<!-- 多对多关联:单向。方式四:使用select引用方式 -->
<collection property="courses" column="sid"
ofType="Course"
select="com.sunwii.mybatis.mapper.CourseMapper.selectByStudent"
fetchType="lazy" />
</resultMap>
<select id="selectById" parameterType="Integer"
resultMap="StudentMap">
select id as sid, name from t_student s where s.id=#{id}
</select> <select id="selectByCourse" parameterType="Integer"
resultMap="StudentMap_basic">
select s.id as sid, s.name from t_student s inner join t_student_course sc
on s.id=sc.student_id and sc.course_id=#{courseId}
</select> <select id="selectStudentByCourseAndScore"
resultMap="StudentMap_basic_ext">
select s.id as sid, s.name,c.name as cousename,sc.score as coursescore from t_student s
inner join t_student_course sc
on s.id=sc.student_id and sc.score>=#{studentCourse.score}
inner join t_course c on c.id=sc.course_id and c.name=#{course.name}
</select> <insert id="insertStudent" parameterType="Student"
keyColumn="id" keyProperty="id" useGeneratedKeys="true">
insert into t_student(name) values(#{name})
</insert> <update id="updateStudent" parameterType="Student">
update t_student set name=#{name} where id=#{id}
</update> <delete id="deleteStudent" parameterType="Student">
delete from t_student where id=#{id}
</delete>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.sunwii.mybatis.mapper.StudentCourseMapper">
<insert id="insertStudentCourse">
insert into
t_student_course(student_id,course_id)
values(#{student.id},#{course.id})
</insert> <delete id="deleteStudentCourse">
delete from
t_student_course where
student_id=#{student.id} and course_id=#{course.id}
</delete> <delete id="deleteStudentCourseByStudent">
delete from
t_student_course where
student_id=#{student.id}
</delete>
</mapper>

业务层实现类:

@Service
public class CourseServiceImpl implements CourseService {
@Autowired
private CourseMapper CourseMapper; @Override
public Course getCourse(Integer id) {
return CourseMapper.selectById(id);
} @Override
@Transactional
public void insertCourse(Course course) {
CourseMapper.insertCourse(course);
} @Override
@Transactional
public void updateCourse(Course course) {
CourseMapper.updateCourse(course);
} @Override
@Transactional
public void deleteCourse(Course course) {
CourseMapper.deleteCourse(course);
} }
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentMapper studentMapper;
@Autowired
private CourseMapper courseMapper;
@Autowired
private StudentCourseMapper studentCourseMapper; @Override
public Student getStudent(Integer id) {
return studentMapper.selectById(id);
} @Override
@Transactional
public void insertStudent(Student student) {
List<Course> courses = student.getCourses(); // 如果需要的话,就先新增课程
if (courses != null) {
for (Course course : courses) {
if (course != null && course.getId() == null) {
courseMapper.insertCourse(course);
}
}
}
studentMapper.insertStudent(student); // 添加选课表
if (courses != null) {
for (Course course : courses) {
if (course != null) {
studentCourseMapper.insertStudentCourse(student, course);
}
}
}
} @Override
@Transactional
public void updateStudent(Student student) {
List<Course> courses = student.getCourses(); if (courses != null) {
// 如果需要的话,就先新增课程
for (Course course : courses) {
if (course != null && course.getId() == null) {
courseMapper.insertCourse(course);
}
}
} studentMapper.updateStudent(student); // 修改选课表
if (courses != null) {
//删除旧的选课表记录
studentCourseMapper.deleteStudentCourseByStudent(student); for (Course course : courses) {
if (course != null) {
studentCourseMapper.insertStudentCourse(student, course);
}
}
}
} @Override
@Transactional
public void deleteStudent(Student student) {
studentMapper.deleteStudent(student); //删除选课表记录
studentCourseMapper.deleteStudentCourseByStudent(student);
} @Override
public List<Student> getStudentByCourseAndScore(String courseName,Integer score) {
return studentMapper.selectStudentByCourseAndScore(new Course(courseName), new StudentCourse(score));
} }

测试类:

public class TestMany2Many {
private ApplicationContext context = SpringUtil.getContext();
private StudentService studentService = (StudentService) context.getBean(StudentService.class);
private CourseService courseService = (CourseService) context.getBean(CourseService.class); /**
* 插入学生信息(可以同时新增不存在的课程,同时进行选课)
*/
@Test
public void testStudentInsert() {
// 多对多:添加。
Student student = new Student();
student.setName("sssss-1"); // 级联新增的课程
Course course = new Course("course-1"); // 非新增的课程
Course course2 = courseService.getCourse(2); student.getCourses().add(course2);
student.getCourses().add(course); studentService.insertStudent(student);
} /**
* 新增学生信息(可以暂时没有选课)
*/
@Test
public void testEmployeeInsert2() {
// 多对多:添加。
Student student = new Student();
student.setName("sssss-2"); studentService.insertStudent(student);
} /**
* 查询学生信息(可以有延迟加载选课记录)
*/
@Test
public void testStudentSelect() {
// 多对一:查询。
int id = 1;
Student student = studentService.getStudent(id); System.out.println(student.toLazyString());
System.out.println(student);
} /**
* 更新学生信息(选课记录是否要更改、是否要删除和重新插入、是否要清空取决于程序)
*/
@Test
public void testStudentUpdate() { // 多对多:添加。
int id = 4;
Student student = studentService.getStudent(id);
student.setName("sssss-444444444-2"); // 级联新增的课程
Course course = new Course("course-xx"); // 非新增的课程
Course course2 = courseService.getCourse(1); student.getCourses().add(course);
student.getCourses().add(course2); // 设置0长度代表清空课程
// student.setCourses(new ArrayList<Course>()); // 设置为null代表不修改
// student.setCourses(null); studentService.updateStudent(student);
} /**
* 删除学生信息(会把选课记录删除)
*/
@Test
public void testStudentDelete() {
int id = 4;
studentService.deleteStudent(new Student(id));
} /**
* 查询一门课程(以及学生信息)
*/
@Test
public void testCourseSelect() { // 多对多:查询
int id = 1;
Course course = courseService.getCourse(id);
System.out.println(course.toLazyString());
System.out.println(course);
} /**
* 查询“数学"成绩90分以上的学生
*/
@Test
public void testCourseWithScoreSelect() { // 多对多:查询
int id = 1;
String courseName = "数学";
Integer score = 90; List<Student> students = studentService.getStudentByCourseAndScore(courseName, score); for (Student student : students) {
System.out.print(student.toLazyString()+"-------");
StudentExt studentExt = (StudentExt)student;
System.out.println(studentExt.getCourseName()+":"+studentExt.getCourseScore());
//System.out.println(courseName+":"+score);
} //结果:
//Student:{id: 1 ; name: 小红}-------数学:95
//Student:{id: 3 ; name: 小青}-------数学:92 } }

注解版本:

注解版本只是将Mapper映射文件去掉,将映射注解到Mapper接口中(如果需要则再添加动态sql提供器类),其它东西不变。

Mapper接口(注解版):

public interface CourseMapper {
public static final String selectById = "select id as cid,name from t_course where id=#{id}";
public static final String selectByStudent = ""
+ "select c.id as cid, c.name from t_course "
+ "c inner join t_student_course sc on "
+ "c.id=sc.course_id and sc.student_id=#{studentId}";
public static final String insert = "insert into t_course(name) values(#{name})";
public static final String update = "update t_course set name=#{name}";
public static final String delete = "delete from t_course where id=#{id}"; public static final String many2many = "com.sunwii.mybatis.mapper.StudentMapper.selectByCourse"; @Select(selectById)
@Results(id = "CourseMap", value = { @Result(property = "id", column = "cid"),
@Result(property = "name", column = "name"),
@Result(property = "students", column = "cid",
many = @Many(
select = many2many,
fetchType = FetchType.LAZY))
})
public Course selectById(Integer id); @Select(selectByStudent)
@Results(id = "CourseMap_basic", value = {
@Result(property = "id", column = "cid"),
@Result(property = "name", column = "name")
})
public List<Course> selectByStudent(Student studentId); @Insert(insert)
@Options(keyColumn = "id", keyProperty = "id", useGeneratedKeys = true)
public int insertCourse(Course course); @Update(update)
public int updateCourse(Course course); @Delete(delete)
public int deleteCourse(Course course);
}
public interface StudentMapper {
public static final String selectById = "select id as sid,name from t_student where id=#{id}";
public static final String selectByCourse = ""
+ "select s.id as sid, s.name from t_student s "
+ " inner join t_student_course sc"
+ " on s.id=sc.student_id and sc.course_id=#{courseId}";
public static final String selectStudentByCourseAndScore = ""
+ "select s.id as sid, s.name,c.name as cousename,sc.score as coursescore "
+ "from t_student s inner join t_student_course sc "
+ "on s.id=sc.student_id and sc.score>=#{studentCourse.score} "
+ "inner join t_course c on c.id=sc.course_id and c.name=#{course.name}";
public static final String insert = "insert into t_student(name) values(#{name})";
public static final String update = "update t_student set name=#{name} where id=#{id}";
public static final String delete = "delete from t_student where id=#{id}"; public static final String many2many = "com.sunwii.mybatis.mapper.CourseMapper.selectByStudent"; @Select(selectById)
@Results(id="StudentMap",value= {
@Result(property = "id", column = "sid"),
@Result(property = "name", column = "name"),
@Result(property = "courses",column = "sid",
many=@Many(
select = many2many,
fetchType = FetchType.LAZY
))
})
public Student selectById(Integer id); @Insert(insert)
@Options(keyColumn = "id", keyProperty = "id", useGeneratedKeys = true)
public int insertStudent(Student employee); @Update(update)
public int updateStudent(Student employee); @Delete(delete)
public int deleteStudent(Student employee); @Select(selectByCourse)
@Results(id="StudentMap_basic", value = {
@Result(property = "id", column = "sid"),
@Result(property = "name", column = "name")
})
public List<Student> selectByCourse(Integer courseId); @Select(selectStudentByCourseAndScore)
@Results(id="StudentMap_basic_ext", value = {
@Result(property = "id", column = "sid"),
@Result(property = "name", column = "name"),
})
public List<Student> selectStudentByCourseAndScore(@Param("course") Course course,
@Param("studentCourse") StudentCourse studentCourse); }
public interface StudentCourseMapper {
public static final String insert="insert into t_student_course(student_id,course_id) values(#{student.id},#{course.id})";
public static final String delete="delete from t_student_course where student_id=#{student.id} and course_id=#{course_id}";
public static final String deleteByStudent="delete from t_student_course where student_id=#{student.id}"; @Insert(insert)
public int insertStudentCourse(@Param("student") Student student, @Param("course") Course course); @Delete(delete)
public int deleteStudentCourse(@Param("student") Student student, @Param("course") Course course); @Delete(deleteByStudent)
public int deleteStudentCourseByStudent(@Param("student") Student student);
}

由于注解版在定义resultMap(即@Results)时无法使用type属性定义返回的封装类型,所以测试类需要修改一点:

/**
* 查询“数学"成绩90分以上的学生
*/
@Test
public void testCourseWithScoreSelect() {
int id = 1;
String courseName = "数学";
Integer score = 90; List<Student> students = studentService.getStudentByCourseAndScore(courseName, score); for (Student student : students) {
System.out.print(student.toLazyString()+"-------");
//注解版无法使用resultMap的type属性,不能直接转化
//StudentExt studentExt = (StudentExt)student;
//System.out.println(studentExt.getCourseName()+":"+studentExt.getCourseScore());
System.out.println(courseName+":"+score);
} //结果:
//Student:{id: 1 ; name: 小红}-------数学:95
//Student:{id: 3 ; name: 小青}-------数学:92 }

Mybatis中使用collection进行多对多双向关联示例(含XML版与注解版)的更多相关文章

  1. Java进阶知识10 Hibernate一对多_多对一双向关联(Annotation+XML实现)

    本文知识点(目录): 1.Annotation 注解版(只是测试建表)    2.XML版 的实现(只是测试建表)    3.附录(Annotation 注解版CRUD操作)[注解版有个问题:插入值时 ...

  2. Java进阶知识12 Hibernate多对多双向关联(Annotation+XML实现)

    1.Annotation 注解版 1.1.应用场景(Student-Teacher):当学生知道有哪些老师教,老师也知道自己教哪些学生时,可用双向关联 1.2.创建Teacher类和Student类 ...

  3. Mybatis中使用association及collection进行一对多双向关联示例(含XML版与注解版)

    XML版本: 实体类: package com.sunwii.mybatis.bean; import java.util.ArrayList; import java.util.List; impo ...

  4. Mybatis中的collection、association来处理结果映射

    前不久的项目时间紧张,为了尽快完成原型开发,写了一段效率相当低的代码. 最近几天闲下来,主动把之前的代码优化了一下:)   标签:Java.Mybatis.MySQL 概况:本地系统从另外一个系统得到 ...

  5. hibernate多对一双向关联

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  6. Hibernate多对多双向关联的配置

    Hibernate的双向多对多关联有两种配置方法:那我们就来看看两种方案是如何配置的.  一.创建以各自类为类型的集合来关联 1.首先我们要在两个实体类(雇员<Emploee>.工程< ...

  7. Hibernate从入门到精通(十一)多对多双向关联映射

    上次我们在中Hibernate从入门到精通(十)多对多单向关联映射讲解了一下多对多单向关联映射,这次我们讲解一下七种映射中的最后一种多对多双向关联映射. 多对多双向关联映射 按照我们之前的惯例,先看一 ...

  8. Hibernate(十一)多对多双向关联映射

    上次我们在中Hibernate从入门到精通(十)多对多单向关联映射讲解了一下多对多单向关联映射,这次我 们讲解一下七种映射中的最后一种多对多双向关联映射. 多对多双向关联映射 按照我们之前的惯例,先看 ...

  9. Hibernate在关于一对多,多对一双向关联映射

    [Hibernate]之关于一对多,多对一双向关联映射 因为一对多.和多对一的双向关联映射基本上一样,所以这里就一起写下来! Annotations配置 @Entity @Table(name=&qu ...

随机推荐

  1. [技术博客] 数据库1+N查询问题

    目录 问题简述 问题解决 group的方法简化查询 改正后的代码 作者:庄廓然 问题简述 本次开发过程中我们用到了rails的orm框架,使用orm框架可以很方便地进行对象的关联和查询,例如查询一个用 ...

  2. 用JAVA把内存里的二进制文件打包成ZIP包

    import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.ut ...

  3. intellij idea远程调试

    有时候发布后的包不得不进行debug,但是又不方便本地开发环境直接debug模拟,所以不得不需要远程debug. 启动参数 首先在服务端使用JVM的-Xdebug参数启动Jar包. java -Xde ...

  4. 防止同一IP多次请求攻击

    防止同一IP多次请求攻击 防止入侵者,通过死循环同一时间批量向服务器请求数据,导致服务器内存开销不断膨胀,最后直接瘫痪. 一. 新增一个spring的拦截器 , 拦截所有请求 <mvc:inte ...

  5. Python中的日志记录方案-logging模块&loguru模块

    原文链接 原创: 崔庆才 在 Python 中,一般情况下我们可能直接用自带的 logging 模块来记录日志,包括我之前的时候也是一样.在使用时我们需要配置一些 Handler.Formatter ...

  6. SoapUI: 设置case的属性变量

    琐碎的东西也想一点一滴的记下来

  7. 目前流行前端几大UI框架排行榜

    在前端项目开发过程中,总是会引入一些UI框架,已为方便自己的使用,很多大公司都有自己的一套UI框架,下面就是最近经常使用并且很流行的UI框架. 一.Mint UI 流行指数:★★★★ Mint UI是 ...

  8. Spring Web Flux 相关概念

    Reactive Streams.Reactor 和 Web Flux 上面介绍了反应式编程的一些概念,以及 Reactor 和 Web Flux.可能读者看到这里有些乱.这里介绍一下三者的关系.其实 ...

  9. vue---将json导出Excel的方法

    在做数据表格渲染的时候,经常遇到的需求的就是将导出excel,下面是使用vue进行项目数据进行导出的方法. 一.安装依赖 npm i -S file-saver npm i -S xlsx 二.在sr ...

  10. 理解 uptime 的:“平均负载”? 如何模拟测试

    每次发现系统变慢时,我们通常做的第一件事,就是执行 top 或者 uptime 命令,来了解系统的负载情况.比如像下面这样,我在命令行里输入了 uptime 命令,系统也随即给出了结果. [root@ ...