MyBatis系列的上一篇博客发表时,笑笑还没有出生。转眼间八个月过去了,他已经是个大宝宝了。这么长时间未更新MyBatis系列的博客,想来真是罪过。不过有了宝宝之后,的确会分散自己很大一部分精力。
今天的示例是多对多关联的查询,这是在上一篇博客(MyBatis多对多保存示例)的基础上完成的,仍然是处理学生与课程之间的多对多关联(一个学生可以选修多门课程,一门课程可以被多个学生选修),相关的实体类和表结构信息请参考上篇博客。
从本篇博客起,示例工程就不再用ant组织,而改用eclipse(示例工程源码及数据库脚本下载地址:http://down.51cto.com/data/1143560)。
首先实现学生端功能,即根据id查询出学生及其选修的课程。步骤如下:
1、在StudentMapper.xml中编写id为“studentResultMap”的resultMap元素,如下:
<!-- 查询学生的结果映射,只映射简单属性 --> <resultMap id="simpleStudent" type="Student"> <id property="id" column="s_id" /> <result property="name" column="s_name" /> <result property="gender" column="s_gender" /> <result property="major" column="s_major" /> <result property="grade" column="s_grade" /> </resultMap> <!-- 查询学生的结果映射,含指导教师、选修课程等复杂属性的映射,从simpleStudent继承而来,提高resultMap的灵活性和重用性 --> <resultMap id="studentResultMap" type="Student" extends="simpleStudent"> <!--association的嵌套的结果映射方式。 --> <association property="supervisor" javaType="Teacher" resultMap="com.abc.mapper.TeacherMapper.simpleTeacher"> </association> <!-- 嵌入的select查询方式,查询学生选修的课程。采用了CourseMapper.xml文件中的id为getByStudentId的select元素,这里的com.abc.mapper.CourseMapper是其命名空间名 --> <collection property="courses" ofType="Course" select="com.abc.mapper.CourseMapper.getByStudentId" column="s_id"> </collection> </resultMap>
这里的关键点在于,为了查询学生选修的课程,用到了collection元素,其查询方式是嵌套的select方式。其select语句采用了CourseMapper.xml文件中的id为getByStudentId的select元素,这里的com.abc.mapper.CourseMapper是其命名空间名(关于collection元素的嵌套select语句的方式,请参考本系列的博文:MyBatis collection的两种形式)。注意这里用到了resultMap元素的继承,提高resultMap元素的灵活性和重用性。
2、在CourseMapper.xml文件中相应的select元素及结果映射如下所示:
<!--课程实体映射--> <resultMap id="simpleCourse" type="Course"> <id property="id" column="course_id"/> <result property="courseCode" column="course_code"/> <result property="courseName" column="course_name"/> </resultMap> <select id="getByStudentId" parameterType="int" resultMap="simpleCourse"> select c.id course_id,course_code,course_name from course c,student_course sc where sc.student_id=#{id} and sc.course_id = c.id </select>
测试类如下:
package com.demo; import java.util.List; import org.springframework.context.ApplicationContext; import com.abc.service.CourseService; import com.abc.service.StudentService; import com.abc.domain.Course; import com.abc.domain.Student; import com.abc.domain.Teacher; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ManyToManyQuery { private static ApplicationContext ctx; static { //在类路径下寻找spring主配置文件,启动spring容器 ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); } public static void main(String[] args) { int i = 0, length = 0; List<Course> list = null; StudentService studentService = (StudentService)ctx.getBean("studentService"); Student student = studentService.getById(7); //获取该学生选修的课程 list = student.getCourses(); StringBuilder info = new StringBuilder("学生姓名:"); info.append(student.getName()); info.append(" "); length = list.size(); while(i < length) { info.append("所选课程名称:"); info.append(list.get(i).getCourseName()); info.append(" "); i++; } System.out.println(info.toString()); } }
注意,与前面的工程相比,本工程的文件布局和名称都有一些变化,新增了com.abc.service包,用到了更多的Spring的相关知识。具体内容请参看作者的公开课:http://bbs.51cto.com/open/do/course/cid/65。
运行结果如下:
现在实现课程端功能,即根据id查询出课程及选修这门课程的学生。步骤如下:
1、在CourseMapper.java中声明方法getById,即根据id查询课程。代码如下:
public Course getById(int id);
2、在CourseMapper.xml中编写对应的select语句,如下:
<!--根据id查询课程及选修的学生--> <select id="getById" parameterType="int" resultMap="courseResutMap"> select c.id course_id,c.course_code course_code,c.course_name course_name, s.id s_id, s.name s_name, s.gender s_gender, s.grade s_grade, s.major s_major from course c left join student_course sc on c.id = sc.course_id left join student s on sc.student_id = s.id where c.id = #{id} </select>
3、此select语句用到了id为courseResutMap的resultMap元素,如下:
<!--课程实体映射,映射简单属性--> <resultMap id="simpleCourse" type="Course"> <id property="id" column="course_id"/> <result property="courseCode" column="course_code"/> <result property="courseName" column="course_name"/> </resultMap> <!--课程实体映射,除映射简单属性,还包含students复杂属性映射--> <resultMap id="courseResutMap" type="Course" extends="simpleCourse"> <collection property="students" resultMap="com.abc.mapper.StudentMapper.simpleStudent"/> </resultMap>
这里的关键点还是用到了collection元素,只是这次用到了嵌套的resultMap形式(关于collection元素的嵌套的resultMap形式,请参考本系列的博文:MyBatis collection的两种形式),而且在这里也同样用到了resultMap元素的继承。simpleStudent是StudentMapper.xml文件中的resultMap元素,com.abc.mapper.StudentMapper是其命名空间名。
请注意,id为“simpleStudent”和“simpleCourse”的两个resultMap元素都得到了重用。其中,StudentMapper.xml和CourseMapper.xml中各引用了simpleStudent一次,CourseMapper.xml中引用了simpleCourse两次。
测试类如下:
package com.demo; import java.util.List; import org.springframework.context.ApplicationContext; import com.abc.service.CourseService; import com.abc.service.StudentService; import com.abc.domain.Course; import com.abc.domain.Student; import com.abc.domain.Teacher; import org.springframework.context.support.ClassPathXmlApplicationContext; public class ManyToManyQuery { private static ApplicationContext ctx; static { //在类路径下寻找spring主配置文件,启动spring容器 ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); } public static void main(String[] args) { int i = 0, length = 0; List<Student> list = null; CourseService courseService = (CourseService)ctx.getBean("courseService"); Course course = courseService.getById(1); //获取选修了此课程的学生 list = course.getStudents(); length = list.size(); StringBuilder info = new StringBuilder("课程名称:"); info.append(course.getCourseName()); info.append(" 选修此课程的学生姓名:"); while(i < length) { info.append(list.get(i).getName()); info.append(" "); i++; } System.out.println(info.toString()); } }
执行结果如下:
猛戳这里全面系统地学习MyBatis 3
MyBatis技术交流群:188972810,或扫描二维码:
【MyBatis学习笔记】系列之预备篇一:ant的下载与安装
【MyBatis学习笔记】系列之预备篇二:ant入门示例
【MyBatis学习笔记】系列之一:MyBatis入门示例
【MyBatis学习笔记】系列之二:MyBatis增删改示例
【MyBatis学习笔记】系列之三:MyBatis的association示例
【MyBatis学习笔记】系列之四:MyBatis association的两种形式
【MyBatis学习笔记】系列之五:MyBatis与Spring集成示例
【MyBatis学习笔记】系列之六:MyBatis与Spring集成示例续
【MyBatis学习笔记】系列之七:MyBatis一对多双向关联
【MyBatis学习笔记】系列之八:MyBatis MapperScannerConfigurer配置
【MyBatis学习笔记】系列之九:MyBatis collection的两种形式
【MyBatis学习笔记】系列之十:MyBatis日志之Log4j示例
【MyBatis学习笔记】系列之十一:MyBatis多参数传递之注解方式示例
【MyBatis学习笔记】系列之十二:MyBatis多参数传递之默认命名方式示例
【MyBatis学习笔记】系列之十三:MyBatis多参数传递之Map方式示例
【MyBatis学习笔记】系列之十四:MyBatis中的N+1问题
【MyBatis学习笔记】系列之十五:MyBatis多参数传递之混合方式
【MyBatis学习笔记】系列之十六:Spring声明式事务管理示例
【MyBatis学习笔记】系列之十七:MyBatis多对多保存示例
【MyBatis学习笔记】系列之十八:MyBatis多对多关联查询示例
【MyBatis学习笔记】系列之十九:如何在MyBatis-3.2.7中使用Log4j2 rc2
MyBatis中如何通过继承SqlSessionDaoSupport来编写DAO(一)
MyBatis中如何通过继承SqlSessionDaoSupport来编写DAO(二)