MyBatis Association Mapping: One-to-Many and Many-to-One

1 Introduction

One-to-many is a very common relationship in web projects. For example: a class corresponds to multiple students, and a student belongs to only one class. A one-to-many relationship in a database usually uses a primary and foreign key association, and the foreign key column should be on the many side. Below we demonstrate how to use MyBatis to handle this relationship with a code example.

2. Example: Classroom and Students

(1) MySQL part

For the convenience of description, we create two tables: student_inf table and classroom_inf table
classroom_inf table:

CREATE TABLE `classroom_inf` (
  `classroom_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`classroom_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

student_inf table:

CREATE TABLE `student_inf` (
  `student_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `age` int(11) DEFAULT NULL,
  `classroom_id` int(11) NOT NULL,
  PRIMARY KEY (`student_id`),
  KEY `classroom_id` (`classroom_id`),
  CONSTRAINT `student_inf_ibfk_1` FOREIGN KEY (`classroom_id`) REFERENCES `classroom_inf` (`classroom_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

Then insert sample data into the table, as shown in the figure:
write picture description here

write picture description here


(2) Create persistent objects

The first is the Student class.
Since the Student class belongs to the more side, we should add a classRoom attribute. The type of this attribute should be the 1 side, that is, the ClassRoom type.
The code is as follows:
com/demo/entity/Student.java

public class Student
{
    private Integer id;
    private String name;
    private Integer age;
    //每个人对应一个教室
    private ClassRoom classRoom;

    public Student(){}

    public Student(String name,Integer age)
    {
        this.name = name;
        this.age = age;
    }

    //省略setter、getter方法
}

Then there is the ClassRoom class.
Since ClassRoom belongs to the 1 side, that is, a classroom can have multiple students, so we should define a students property, which is a List collection to map this relationship.
The code is as follows:
com/demo/entity/ClassRoom.java

public class ClassRoom 
{
    private Integer id;
    private String name;

    private List<Student> students;

    public ClassRoom() {}

    public ClassRoom(String name) 
    {
        this.name = name;
    }

    //省略getter、setter方法
}

(3) Create an XML entity configuration file

On the more side, the association mapping <association.../> should be used, and the explanation of the <association.../> element is as follows:
1. property: indicates the return type Student attribute name classRoom
2. javaType: indicates the name corresponding to the attribute, namely ClassRoom
here It should be noted that since the Student table and the ClassRoom table have the same column name: name, in order to prevent confusion, we need to alias the name column of one of the tables in the select statement. Otherwise, in the actual search, when we want to output the name of a student, we find that the output is the name of the classroom.
Look at the source code below:

com/demo/entity/StudentMapper.xml

<?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.demo.entity.StudentMapper">  

    <resultMap id="studentResultMap" type="com.demo.entity.Student">
        <id property="id" column="student_id" />
        <!--表中的实际列名为name,为了防止混淆这里取student_name,同时也要在下面的SQL语句中声明-->
        <result property="name" column="student_name" />
        <result property="age" column="age" />
        <association property="classRoom" javaType="com.demo.entity.ClassRoom">
            <id property="id" column="classroom_id" />
            <result property="name" column="name" />
        </association>
    </resultMap>

    <!--通过学生id查找这个学生的信息-->
    <select id="selectStudentById" parameterType="int" resultMap="studentResultMap">
        SELECT
             c.*,
             s.*,
             s.name student_name <!--给student_inf表的name列名取别名-->
        FROM classroom_inf c,student_inf s
        WHERE c.classroom_id = s.classroom_id AND s.student_id = #{id}
    </select>

    <!--查找所有学生信息-->
    <select id="selectStudent" resultMap="studentResultMap">
        SELECT 
            c.*,
            s.*,
            s.name student_name
        FROM classroom_inf c,student_inf s
        WHERE c.classroom_id = s.classroom_id
    </select>

</mapper>


On the side of 1, the collection element should be used in the resultMap element to map this relationship. The <collection.../> element is explained as follows:
1. property: indicates the return type List<Student> property name students
2. ofType: the element in the collection Types of.
com/demo/entity/ClassRoomMapper.xml

<?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.demo.entity.ClassRoomMapper">    

    <resultMap id="classRoomMap" type="com.demo.entity.ClassRoom">
        <id property="id" column="classroom_id" />
        <result property="name" column="name" />

        <collection property="students" ofType="com.demo.entity.Student">
            <id property="id" column="student_id" />
            <!--这里同样需要取别名student_name-->
            <result property="name" column="student_name" />
            <result property="age" column="age" />
        </collection>

    </resultMap>

    <!--查找所有教室信息和对应的学生信息-->
    <select id="selectClassRoom" resultMap="classRoomMap">
        SELECT 
            c.*,
            s.*,
            s.name student_name
        FROM classroom_inf c, student_inf s
        WHERE c.classroom_id = s.classroom_id
    </select>

    <!--根据id查找所有教室信息和对应的学生信息-->
    <select id="selectClassRoomById" resultMap="classRoomMap" parameterType="int">
        SELECT 
            c.*,
            s.*,
            s.name student_name
        FROM classroom_inf c, student_inf s
        WHERE c.classroom_id = s.classroom_id AND c.classroom_id = #{id}
    </select>

</mapper>

(4) Test class

com/demo/Main.java

public class Main 
{
    public static void main(String[] args) throws IOException
    {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = sqlSessionFactory.openSession();

        //查找所有教室信息
        List<ClassRoom> classList =
             session.selectList("com.demo.entity.ClassRoomMapper.selectClassRoom");
        //循环输出内容
        for(ClassRoom classRoom : classList)
        {
            System.out.println(classRoom.getName());
            //获取每个教室对应的学生
            List<Student> students = classRoom.getStudents();
            for(Student student : students)
                System.out.println(student.getName() + " " + student.getAge());
        }

        //查找所有学生信息
        List<Student> studentList =
             session.selectList("com.demo.entity.StudentMapper.selectStudent");
        //循环输出学生信息
        for(Student student : studentList)
        {
            System.out.println(student.getName() + " " + student.getAge() + " " +
                 student.getClassRoom().getName());
        }

        session.commit();
        session.close();
    }
}

output:

1401教室
李同学 17
张同学 18
1402教室
刘同学 19
1403教室
陈同学 20
李同学 17 1401教室
张同学 18 1401教室
刘同学 19 1402教室
陈同学 20 1403教室

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326063995&siteId=291194637