mybatis Learning Notes of J2EE Series (V) -- mybatis Relational Mapping (One-to-Many Mapping)

Keywords: xml Attribute Mybatis Junit

This blog is about one-to-many mapping. Take the class as an example.

On the basis of the previous project:

1. Create a new table t_grade in the database and add data:


Establish a one-to-many association between the table and t_student:


Add the field gradeId in table t_student:


2. new class 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;
	}
	@Override
	public String toString() {
		return "Grade [id=" + id + ", gradeName=" + gradeName + ", students=" + students + "]";
	}
	
	
	
}
2. New Grade database operation interface GradeMapper:

package com.test.mappers;

import com.test.model.Grade;

public interface GradeMapper {

	
	public Grade findById(Integer id);
	

}

There is only one way to query grade information based on id.

3. Implement this method:

<?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.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> 

This is similar to one-to-many. In the result mapping defined, association is achieved by <collection> tag: the column id value of the query result is passed into the com.test.mappers.StudentMapper.findByGradeId method.

The execution result of this method is assigned to the students property of the Grade class object.

4. In Student Mapper, we add the method of inquiring students'information through grade Id:

public Student findByGradeId(Integer gradeId);

This method is implemented in StudentMapper.xml:

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


5. New test class 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("Inquiry grade (with student information)");
		Grade grade = gradeMapper.findById(2);
		System.out.println(grade);
	}
	
	
}

Running the test function, the console output is:

[main] INFO com.test.service.GradeTest - Query grade (with student information)
Grade [id=2, gradeName = sophomore, students=[Student [id=4, name = Li Si 2, age=11, address=Address [id=2, sheng = Guangxi Province, shi = Nanning City, qu = Xingning District], Student [id=5, name = Wang Wu, age=15, address=Address [id=1, sheng = Guangxi Province, shi = Nanning City, qu = Qingxiu District]]
The information of all the students in this grade is inquired through the grade.


Speak about the implementation process:

1) Running the test method, the student id=2 is passed into the findById method in GradeMapper.xml. Execute the sql statement of this method, and the query results are as follows:

2) Encapsulate the returned results according to the result mapping GradeResult:

2.1) The value of the id column is paid to the id attribute of the Grade class object, and the value of the gradeName column is paid to the gradeName attribute of the Grade class object. When scanning the < Collection > tag, pass the value of the id column to the findByGradeId method in StudentMapper.xml.

2.2) Execute the sql statement of findByGradeId method and get the query result:

Encapsulate the returned results according to the result mapping StudentResult: It also queries the address information of the students in t_address (this process is in one-to-one relational mapping).

As I said, I will not talk about the process here.

3) Print out the grade information after getting the grade result with the students.


Above all, we can query all the students'information when we query the grade information.


Furthermore, when inquiring about students'information, we also hope to be able to inquire about the information of the class where the students are in. To this end, the following modifications are made:

1. Add the attribute grade to the Student class:


Generate the get and set methods for this property, and re-create the toString method of the Student class.

2. Modify the result mapping StudentResult in StudentMapper.xml as follows:

<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>

Here we add an additional method to get the class information by passing the value of the column gradeId to GradeMapper.findById method, and pass the class information to the grade attribute.


3. New test methods in StudentTest 3:

@Test
	public void testFindStudentWithGrade() {
		logger.info("Query students (with grades)");
		Student student = studentMapper.findStudentWithAddress(2);
		System.out.println(student);
	}
Run this test method:



The program reported an error, which was a stack overflow. The reason for this problem is that the program has fallen into a dead cycle. This method includes printing student information.

The toString method of Student class shows that the class information of the student is printed when the student information is printed. The toString method of Grade class displays printing

Class information will be printed when the class information. This leads to a dead cycle of printing.


To solve this problem, modify the toString method of Grade class:

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

Only grade information is printed here, instead of student information in grade.


Running the above test method, the console output is:

[main] INFO com.test.service.StudentTest - Query students (with grade)
Student [id=2, name = Li Si, age=11, address=Address [id=2, sheng = Guangxi Province, shi = Nanning City, qu = Xingning District], grade=Grade [id=1, gradeName = Dayi]]

The information of the students and the class and address information of the students are output here.


Posted by discorevilo on Sun, 09 Dec 2018 23:48:05 -0800