Mybatis 08

8.1 多对一 和 一对多


在这里插入图片描述

  • 多个学生,对应一个老师
  • 对于学生来说,多个学生可能同时关联一个老师。
  • 对于老师而言,一个老师 教了很多的学生。类似于一个老师集合了很多学生。

在结果映射 resultMap 中,associationcoLiction 是搭建 复杂查询的关键 标签。

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=utf8INSERT 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');

在这里插入图片描述

  • 查询所有的学生信息,一级对应的老师的信息。

正常的 SQL:select s.id,s.name,t.name from student as s inner join teacher as t where s.tid = t.id;

当然 我们也可以 用 下面这种 多此一举的子查询。

select s.id,s.name,t.name as 老师 from student s inner join teacher t where s.tid = (select id from teacher);

但实际上,我们 在使用 mybatis 的时候,目前来看。无论是 注解的方式,还是 select 标签的方式,都是无法直接实现的。因为 我们 能够提供的返回类型只能是 一个!而 注解 只能做 简单的 SQL 语句处理。

那么我们就要学习一个 resultMap 里 两个 新的 子标签了。associationcoLiction


8.1.1 association 多对一

association 多对一,指的是 多个元素,关联一个元素,或者说 多个 对象 同时关联了一个 对象!

这个时候我们通常采取 两种方式:resultMap 子查询resultMap 结果关联

比如说 你查询的 学生表 里面 现在有一个 tid,我们可以 本来是 可以 通过 tid 查询到 教师信息,完成目标的。但我们 无法 像 SQL 那样灵活方便。那我们 就必须要 对 最终的结果集进行分析了。

最终的结果集是 学生的 id 和 name,教师的 name。也就是说 我们 最终的结果集 是 没有 tid 的。

  1. resultMap 子查询

首先,肯定是要 提供两个表的查询的。
select * from teacher where id = #{tid} 只有查到了 teacher 对象,才能够 知道 teacher 的 name。而我们 肯定是 通过 查询到的 tid 找到 这个 teacher 对象的。

select * from student 然后,我们 查 student 就正常查就行,因为最后处理 是 要在 resultMap 里面进行的。

<mapper namespace="com.muquanyu.Mapper.StudentMapper">
    <select id="getStudentList" resultMap="StudentTeacher">
        select * from mybatis.student
    </select>
    <resultMap id="StudentTeacher" type="com.muquanyu.pojo.Student">
        <result property="id" column="id"></result>
        <result property="name" column="name"></result>
        <association property="teacher" column="tid" javaType="com.muquanyu.pojo.Teacher" select="getTeacher"></association>
    </resultMap>

    <select id="getTeacher" resultType="com.muquanyu.pojo.Teacher">
        select * from mybatis.teacher where id = #{tid}
    </select>

getTeacher 这个方法 它是 不在 我们的 StudentMapper 接口里面 声明的。那 它 怎么能应用呢?又如何能够 有效呢?答案是:利用 resultMap 的 association 子标签 select 属性 绑定 getTeacher 实现 子查询!!!

association 子标签的使用是 先让你 做简单的绑定,就是 属性名是什么,对应的 字段名是什么,然后 要 对 javaType 和 select 进行绑定,javaType 是绑定 你通过 该字段 要去 查一个 什么表,转到java里的意思,就是 你要去查一个 什么对象,然后提供这个 类型就行。那么通过 哪个方法 去查,这个时候 用 select 去绑定 你写在 xml 里面的 sql 方法就行了。

但实际上,我们 无论是 使用 SQL 还是 使用 mybatis 都会发现 这种 子查询的 方式 很麻烦。所以 我们 要 介绍 第二个 方式 “resultMap 结果关联”

  1. resultMap 结果关联

它之所以方便,是因为 我们的 SQL 语句 该是什么样子,就是什么样就行。然后 直接 通过 resultMap 去调节就可以了

<?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="top.muquanyu.Mapper.StudentMapper">
    <resultMap id="StudentMapB" type="top.muquanyu.pojo.Student">
        <id property="id" column="sid"></id>
        <result property="name" column="sname"></result>
        <association property="teacher" javaType="top.muquanyu.pojo.Teacher">
            <id property="id" column="tID"></id>
            <result property="name" column="tname"></result>
        </association>
    </resultMap>

    <select id="getListB" resultMap="StudentMapB">
        select s.id sid,s.name sname,s.tid,t.id tID,t.name tname from
        test.teacher t join test.student s on t.id = s.tid
    </select>
</mapper>

在这里插入图片描述
在这里插入图片描述


8.2.1 collection 一对多

比如:一个老师 拥有 多个 学生,这就是 一对多。

  • 联表查询
<?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="top.muquanyu.Mapper.TeacherMapper">

   <resultMap id="TeacherMap" type="top.muquanyu.pojo.Teacher">
       <id property="id" column="Tid" ></id>
       <result property="name" column="tname" ></result>
       <collection property="students" ofType="top.muquanyu.pojo.Student">
           <id property="id" column="sid"></id>
           <result property="name" column="sname"></result>
           <result property="tid" column="tid"></result>
       </collection>
   </resultMap>


   <select id="getListByID" resultMap="TeacherMap">
       select s.id sid,s.name sname,s.tid tid,t.id Tid,t.name tname from
       test.teacher t join test.student s on s.tid = t.id and t.id = #{id}
   </select>
</mapper>

xml 配置里面的 ofType 代表的是 泛型类型,就是说 你这个集合 泛型是什么类型的。你需要配置一下。

为什么 链表查询的 collection 里面 没有 对应的 javaType 呢?

答:因为不需要!我们联表查询,已经明确的指出 我们要查询的就是一个集合,序列。所以不需要 告诉 collection javaType = ArrayList 了!

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import top.muquanyu.Mapper.TeacherMapper;
import top.muquanyu.pojo.Teacher;
import top.muquanyu.utils.MybatisUtils;

public class 一对多 {
    @Test
    public void test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        for (Teacher teacher : mapper.getListByID(1)) {
            System.out.println(teacher);
        }
        sqlSession.close();
    }
}
  • 子查询

<?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="top.muquanyu.Mapper.TeacherMapper">
    <resultMap id="TeacherMapB" type="top.muquanyu.pojo.Teacher">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <collection property="students" column="id" javaType="ArrayList" ofType="student" select="getStudent"></collection>
    </resultMap>

    <select id="getListByIDB" resultMap="TeacherMapB">
        select * from test.teacher where id = #{id}
    </select>

    <select id = "getStudent" resultType="top.muquanyu.pojo.Student">
        select * from test.student where tid = #{tid}
    </select>

</mapper>

子查询 的 多对一和一对多,column 指的是 哪个字段 可以 跟 你要 关联的表 进行 关联的。比如说 多对一时 的 学生 tid 就是跟 老师表 关联的,所以 要写 column = tid,而 一对多 的 老师的 id 跟 查询学生 时 的 关键条件 where tid = #{tid} 有明显 关联,这个 tid 其实 指的就是 老师 的 id。所以 column = id。 然后 它在 进行 返回的时候,是直接 传参的,也就是说 不用 特别在意 select 绑定的方法 sql 语句 #{参数名} 与 这个 column 绑定的字段名 不一致。因为 是直接 返回 传参的。所以 不需要 名字一致!

javaType 绑定 实体类中的 主 java 类型一对多,链表查询的时候可以不用写!
ofType 绑定 集合中 的 泛型类型


8.2.2 注意点

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

SQL 面试高频问题:

  • MySQL 引擎
  • InnoDB 底层原理
  • 索引的使用
  • 索引优化
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值