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文件中的idgetByStudentIdselect元素,这里的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

运行结果如下:

wKiom1NX0WuQ9mnBAAGF5yfxGfs220.jpg

现在实现课程端功能,即根据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元素的继承simpleStudentStudentMapper.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());
}
}

执行结果如下:

wKioL1NXzrjyebfJAAGS3KWHa6I873.jpg

      猛戳这里全面系统地学习MyBatis 3

      MyBatis技术交流群:188972810,或扫描二维码:

wKioL1SaztmBchKiAADsv4YAWBY259.jpg


【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(二)