Mybatis学习笔记:多对一(association )一对多处理(collection)

Posted 我永远信仰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis学习笔记:多对一(association )一对多处理(collection)相关的知识,希望对你有一定的参考价值。

10、多对一的处理

  • 多个学生,对应一个老师
  • 对于学生来说,关联…多个学生,关联一个老师【多对一】
  • 对于老师而言,集合… 一个老师,有多个学生【一对多】

搭建环境:

建立一张老师表、一张学生表

CREATE TABLE `teacher` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO teacher(`id`, `name`) VALUES (1, "秦老师"); 

CREATE TABLE `student` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  `tid` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO `student` (`id`, `name`, `tid`) VALUES (1, "小明", 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (2, "小红", 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (3, "小张", 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (4, "小李", 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (5, "小王", 1);

测试环境搭建

工具类MybatisUtils

public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            //使用mybatis第一步,获取sqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //既然有了 SqlSessionFactory,我们可以从中获得 SqlSession 的实例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
    public static SqlSession getSqlSession(){
        //设置为true,自动提交事务
        return sqlSessionFactory.openSession(true);
    }

}

1.导入lombok

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.20</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

2.新建实体类 Teacher、Student

@Data
public class Teacher {
    private int id;
    private String name;
}
@Data
public class Student {
    private int id;
    private String name;
    private Teacher teacher;
}

3.新建Mapper接口

public interface StudentMapper {
    //查询所有学生,并且显示其对应的老师的名字
    List<Student> getStudent();

    List<Student> getStudent2();
}
public interface TeacherMapper {
    @Select("select * from teacher where id=#{tid}")
    Teacher getTeacher(@Param("tid") int tid);
}

4.建立Mapper.xml文件

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.yong.dao.StudentMapper">

    <select id="getStudent2" resultMap="StudentAndTeacher2">
        select s.id sid,s.name sname,t.name tname
        from student s 
        join teacher t 
        on s.tid=t.id
    </select>
    
    <resultMap id="StudentAndTeacher2" type="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="Teacher">
            <result property="name" column="tname"/>
        </association>
    </resultMap>


    <!--==============================-->

    <select id="getStudent" resultMap="StudentAndTeacher">
        select * from student
    </select>

    <resultMap id="StudentAndTeacher" type="Student">
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>

    <select id="getTeacher" resultType="Teacher">
        select * from teacher where id=#{id}
    </select>
</mapper>

TeacherMapper.xml暂时不用,可以创建空表

5.在核心配置文件中绑定注册我们的Mapper接口或者文件!【多种方式】

<mappers>
    <!--        将包内的映射器接口实现全部注册为映射器-->
    <!--        <package name="com.yong.dao"/>-->

    <!--        <mapper resource="com/yong/dao/TeacherMapper.xml"/>-->
    <!--        <mapper resource="com/yong/dao/StudentMapper.xml"/>-->
    <mapper class="com.yong.dao.TeacherMapper"/>
    <mapper class="com.yong.dao.StudentMapper"/>
</mappers>

6.测试查询是否成功

在sql中多表查询可以直接用sql进行表连接查出来,但是在mybatis中不行,因为mybatis中的查询结果

是一个对象。

按照查询嵌套处理

解决思路:

​ 1.查询所有学生

​ 2.根据查询出来的学生的tid,寻找对应的老师!

​ 3.使用resultMap,结果集映射。

​ 4.在resultMap中,association:对象,collection:集合

​ 5.嵌套查询语句(子查询)。javaType:对象的类型,select嵌套的标签

<select id="getStudent" resultMap="StudentAndTeacher">
    select * from student
</select>

<resultMap id="StudentAndTeacher" type="Student">
    <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>

<select id="getTeacher" resultType="Teacher">
    select * from teacher where id=#{tid}
</select>

按照结果嵌套处理

<select id="getStudent2" resultMap="StudentAndTeacher2">
    select s.id sid,s.name sname,t.name tname
    from student s 
    join teacher t 
    on s.tid=t.id
</select>

<resultMap id="StudentAndTeacher2" type="Student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>

11、一对多

比如:一个老师有多个学生,那么对于老师而言,就是一对多的关系

复杂的类型 我们需要单独处理

环境搭建

和上面的一样

实体类

@Data
public class Teacher {
    private int id;
    private String name;

    //一个老师有多个学生
    private List<Student> students;
}
@Data
public class Student {
    private int id;
    private String name;
    private int tid;
}

接口

public interface TeacherMapper {
    //获取老师
    List<Teacher> getTeachers();

    //根据id获取老师和他的学生
    List<Teacher> getTeacher(@Param("tid") int id);

    //根据id获取老师和他的学生
    List<Teacher> getTeacher2(@Param("tid") int id);

}

TeacherMapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.yong.dao.TeacherMapper">

    <select id="getTeachers" resultType="Teacher">
        select * from teacher;
    </select>

    <select id="getTeacher" resultMap="TeacherAndStudent">
        select s.id sid,s.name sname,t.name tname,t.id tid
        from student s
        join teacher t
        on s.tid=t.id and t.id=#{tid}
    </select>
    <resultMap id="TeacherAndStudent" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>

    </resultMap>

    <!--=====================================================-->
    <select id="getTeacher2" resultMap="TeacherAndStudent2">
        select * from teacher where id=#{tid};
    </select>
    
    <resultMap id="TeacherAndStudent2" type="Teacher">
        <collection property="students" column="id" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId"/>
    </resultMap>
    
    <select id="getStudentByTeacherId" resultType="Student">
        select * from student where tid=#{tid};
    </select>
</mapper>

按照查询嵌套处理

<select id="getTeacher2" resultMap="TeacherAndStudent2">
    select * from teacher where id=#{tid};
</select>

<resultMap id="TeacherAndStudent2" type="Teacher">
    <collection property="students" column="id" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId"/>
</resultMap>

<select id="getStudentByTeacherId" resultType="Student">
    select * from student where tid=#{tid};
</select>

按照结果嵌套处理

<select id="getTeacher" resultMap="TeacherAndStudent">
    select s.id sid,s.name sname,t.name tname,t.id tid
    from student s
    join teacher t
    on s.tid=t.id and t.id=#{tid}
</select>
<resultMap id="TeacherAndStudent" type="Teacher">
    <result property="id" column="tid"/>
    <result property="name" column="tname"/>
    <collection property="students" ofType="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <result property="tid" column="tid"/>
    </collection>

</resultMap>

小结

1.关联:association 【多对一】

2.集合:collection【一对多】

3.javaType :指定实体类中属性的类型

4.ofType:用来指定映射到List或者集合中的pojo类型,泛型中的约束类型

注意点:

  • 保证SQL的可读性,尽量保证通俗易懂
  • 注意一对多和多对一中,属性名和字段的问题。
  • 如果问题不好排查,可以使用日志,建议使用log4j

以上是关于Mybatis学习笔记:多对一(association )一对多处理(collection)的主要内容,如果未能解决你的问题,请参考以下文章

mybatis框架学习-多表查询

Mybatis学习总结——高级映射(一对一,一对多,多对多)

Mybatis 多表实现多对一查询添加操作

mybatis的学习6____处理多对一的情况

mybatis学习笔记三(关联关系)

MyBatis学习05