J2EE系列之MyBatis学习笔记(五)-- mybatis关系映射(一对多映射)

来源:互联网 发布:海外淘宝首页 编辑:程序博客网 时间:2024/05/22 23:05

这一篇博客讲述一对多关系映射。以班级学生为例。

在上一个工程的基础上:

1.数据库中新建表t_grade,并添加数据:


把这个表和t_student建立一对多关联:


表t_student中添加字段gradeId:


2.新建类Grade:

package com.test.model;import java.util.List;public class Grade {private Integer id;private String gradeName;private List<Student> students;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getGradeName() {return gradeName;}public void setGradeName(String gradeName) {this.gradeName = gradeName;}public List<Student> getStudents() {return students;}public void setStudents(List<Student> students) {this.students = students;}@Overridepublic String toString() {return "Grade [id=" + id + ", gradeName=" + gradeName + ", students=" + students + "]";}}
2.新建Grade的数据库操作接口GradeMapper:

package com.test.mappers;import com.test.model.Grade;public interface GradeMapper {public Grade findById(Integer id);}

这里只有一个方法,就是根据id查询年级信息。

3.实现这个方法:

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.test.mappers.GradeMapper"><resultMap type="Grade" id="GradeResult"><id property="id" column="id"/><result property="gradeName" column="gradeName"/><collection property="students" column="id" select="com.test.mappers.StudentMapper.findByGradeId"></collection></resultMap><select id="findById" parameterType="Integer" resultMap="GradeResult">select * from t_grade where id=#{id}</select></mapper> 

这里和一对多类似。定义的结果映射中,通过<collection>标签实现关联:把查询结果的列id的值传入到com.test.mappers.StudentMapper.findByGradeId方法中,

这个方法的执行结果赋值给Grade类对象的students属性。

4.这里在StudentMapper中添加通过年级Id查询学生信息的方法:

public Student findByGradeId(Integer gradeId);

StudentMapper.xml中实现这个方法:

<select id="findByGradeId" parameterType="Integer" resultMap="StudentResult">select * from t_student where gradeId=#{gradeId}</select>


5.新建测试类GradeTest:

package com.test.service;import org.apache.ibatis.session.SqlSession;import org.apache.log4j.Logger;import org.junit.After;import org.junit.Before;import org.junit.Test;import com.test.mappers.GradeMapper;import com.test.model.Grade;import com.test.util.SqlSessionFactoryUtil;public class GradeTest {private static Logger logger = Logger.getLogger(GradeTest.class);private SqlSession sqlSession = null;private GradeMapper gradeMapper = null;@Beforepublic void setUp() throws Exception {sqlSession = SqlSessionFactoryUtil.openSession();gradeMapper = sqlSession.getMapper(GradeMapper.class);}@Afterpublic void tearDown() throws Exception {sqlSession.close();}@Testpublic void testFindGradeWithStudent() {logger.info("查询年级(带学生信息)");Grade grade = gradeMapper.findById(2);System.out.println(grade);}}

运行测试函数,控制台输出为:

[main] INFO com.test.service.GradeTest - 查询年级(带学生信息)Grade [id=2, gradeName=大二, students=[Student [id=4, name=李四2, age=11, address=Address [id=2, sheng=广西省, shi=南宁市, qu=兴宁区]], Student [id=5, name=王五, age=15, address=Address [id=1, sheng=广西省, shi=南宁市, qu=青秀区]]]]
这里通过年级查询出来这个年级的所有学生信息。


说一下执行过程:

1)运行测试方法,学生id=2传入到GradeMapper.xml中的findById方法中。执行这个方法的sql语句,查询结果为:

2)按照结果映射GradeResult封装返回结果:

2.1)把id列的值付给Grade类对象的id属性,把gradeName列的值付给Grade类对象的gradeName属性。扫描到<collection>标签的时候把id列的值传给StudentMapper.xml中的findByGradeId方法。

2.2)执行findByGradeId方法的sql语句,得到查询结果:

按照结果映射StudentResult封装返回结果:还会到t_address中查询出学生的地址信息(这个过程在一对一关系映射中

讲过),这里就不再讲述过程了。

3)得到带有学生的年级结果后打印出年级信息。


以上就实现了查询年级信息的时候查询出年级的所有学生信息。


进一步的讲,在查询学生信息的时候,我们也希望能够查询出学生所在的班级信息。为此进行如下修改:

1.在Student类中添加属性grade:


生成这个属性的get和set方法,并重新Student类的toString方法。

2.修改StudentMapper.xml中的结果映射StudentResult为:

<resultMap type="Student" id="StudentResult"><id property="id" column="id"/><result property="name" column="name"/><result property="age" column="age"/><association property="address" column="addressId" select="com.test.mappers.AddressMapper.findById"></association><association property="grade" column="gradeId" select="com.test.mappers.GradeMapper.findById"></association></resultMap>

这里多添加了一个通过把列gradeId的值传给GradeMapper.findById方法获取相应的班级信息,并把班级信息传给grade属性。


3.StudentTest3类中新建测试方法:

@Testpublic void testFindStudentWithGrade() {logger.info("查询学生(带年级)");Student student = studentMapper.findStudentWithAddress(2);System.out.println(student);}
运行这个测试方法:



程序报错了,报错为栈溢出。出现这个问题的原因是程序陷入了死循环。这个方法中有打印学生信息,

Student类的toString方法中显示在打印学生信息的时候会打印学生所在的班级信息。Grade类的toString方法显示打印

班级信息的时候会打印班级中的学生信息。这样就陷入了打印死循环。


为了解决这个问题,修改一下Grade类的toString方法:

@Overridepublic String toString() {return "Grade [id=" + id + ", gradeName=" + gradeName + "]";}

这里只打印年级信息,而不再打印年级中的学生信息了。


运行上述测试方法,控制台输出为:

[main] INFO com.test.service.StudentTest - 查询学生(带年级)Student [id=2, name=李四, age=11, address=Address [id=2, sheng=广西省, shi=南宁市, qu=兴宁区], grade=Grade [id=1, gradeName=大一]]

这里输出了学生信息以及学生所在的班级和地址信息。


阅读全文
0 0