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

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

在上一个工程的基础上:

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


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

J2EE系列之MyBatis学习笔记(五)-- mybatis关系映射(一对多映射)_第1张图片

表t_student中添加字段gradeId:

J2EE系列之MyBatis学习笔记(五)-- mybatis关系映射(一对多映射)_第2张图片

2.新建类Grade:

package com.test.model;

import java.util.List;

public class Grade {

	private Integer id;
	private String gradeName;
	private List 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 getStudents() {
		return students;
	}
	public void setStudents(List students) {
		this.students = students;
	}
	@Override
	public 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.实现这个方法:





	
	
	
		
		
		
	
	
	
	

 

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

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

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

public Student findByGradeId(Integer gradeId);

StudentMapper.xml中实现这个方法:



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;
	@Before
	public void setUp() throws Exception {
		sqlSession = SqlSessionFactoryUtil.openSession();
		gradeMapper = sqlSession.getMapper(GradeMapper.class);
	}

	@After
	public void tearDown() throws Exception {
		sqlSession.close();
	}

	@Test
	public 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属性。扫描到标签的时候把id列的值传给StudentMapper.xml中的findByGradeId方法。

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

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

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

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


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


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

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

J2EE系列之MyBatis学习笔记(五)-- mybatis关系映射(一对多映射)_第3张图片

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

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


		
		
		
		
		
	

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


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

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

J2EE系列之MyBatis学习笔记(五)-- mybatis关系映射(一对多映射)_第4张图片

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

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

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


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

@Override
	public 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=大一]]

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


你可能感兴趣的:(Java程序开发)