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

    }

 

posted on 2019-11-06 14:24  Dream Young  阅读(3179)  评论(0编辑  收藏  举报