MyBatis03:嵌套查询、嵌套结果、延迟加载

系列文章目录

MyBatis01:创建、运行、测试一个mybatis项目
MyBatis02:使用MyBatis查询数据
MyBatis03:嵌套查询、嵌套结果、延迟加载
MyBatis04:动态SQL
MyBatis05:类型转换器
MyBatis06:分页插件、MyBatis配置文件中的标签
MyBatis07:MyBatis注解



前言

这篇文章是对查询结果ResultMap的进一学习。前面一篇文章的末尾,简单的介绍了resultType和resultMap的联系与区别。


一、ResultMap

1. 查询语句的执行过程

sql语句查询到结果后,将结果返回给resultMap,由resultMap创建对象。根据column和property的映射关系,获取数据库里字段的值,并将其赋给Java的属性。

2. ResultMap的优势

事实上对于一个复杂的交互代码,可能需要写上千行的代码来实现连接映射(join mapping)使用ResultMap的目的就是让我们只需要使用简单的配置语句,而不需要详细地处理结果映射。对更复杂的语句除了使用一些必须的语句描述外,就不需要做其他的处理了。

3. ResultMap的作用

将查询结果映射为对象,再把对象映射到集合里(因为不知道会查询到多少对象,所以需要将对象映射到集合里)。我们只需要对应好字段属性即可。通过ResultMap建立数据库字段Java属性的映射关系。

4. 数据类型

  1. javaType:实体属性的数据类型,可以省略
  2. jdbcType:数据库字段的数据类型,可以省略

通过mybatis框架的转化器,可以将数据库里的类型转化为Java程序类型

二、一对一,对象属性

背景:为学生的班级对象属性映射值

<sql id="base_info">id,name,sex,birthday,age,classid</sql>
<select id="selectByPrimaryKey" resultMap="baseMap">
    select <include refid="base_info"></include> from student
    where id = #{id}
</select>

一对一的查询语句就是通过某个参数,查询到某个对象

1. 一对一,嵌套查询

根据查询条件column,通过select查询语句将查询到的结果映射给property属性

<association property="clazz" column="classid" select="com.dao.ClazzMapper.selectByPrimaryKey"></association>
标签/属性属性值含义/作用
association标签为对象属性映射值
propertyclazz对象属性
columnclassid作为查询条件的数据库字段
selectcom.dao.ClazzMapper.selectByPrimaryKey调用方法进行查询

完整代码:

 <resultMap id="baseMap2" type="com.bean.Student">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="sex" property="sex"></result>
        <result column="birthday" property="birthday"></result>
        <result column="age" property="age"></result>
        <result column="classid" property="classId"></result>
        <association property="clazz" column="classid" select="com.mapper.ClazzMapper.selectByPrimaryKey"></association>
    </resultMap>
    <select id="selectStudentAndClazz" resultMap="baseMap2">
        select s.*, c.classname from student s left join clazz c on s.classid = c.id where s.id = #{id}
    </select>

2. 一对一,嵌套结果

分别建立对象属性对象属性的属性的映射关系即可

<association property="clazz" javaType="com.bean.Clazz">
    <!--将查询到的学生的classid赋值给班级的id-->
    <id column="classid" property="id"></id>
    <result column="classname" property="classname"></result>
</association>
标签/属性属性值含义/作用
association标签为对象属性映射值
propertyclazz对象属性
javaTypecom.bean.Clazz对象属性的数据类型
id标签用来设置主键
result标签用来设置其他字段
columnclassid数据库的字段
propertyid对象属性的属性

完整代码:

<resultMap id="baseMap3" type="com.bean.Student">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="sex" property="sex"></result>
        <result column="birthday" property="birthday"></result>
        <result column="age" property="age"></result>
        <result column="classid" property="classId"></result>
        <association property="clazz" javaType="com.bean.Clazz">
            <id column="classid" property="id"></id>
            <result column="classname" property="classname"></result>
        </association>
    </resultMap>
    <select id="selectStudentAndClazz2" resultMap="baseMap3">
        select s.*, c.classname from student s left join clazz c on s.classid = c.id where s.id = #{id}
    </select>

这里是将从数据库中查询到的结果,赋值给Java属性。

三、一对多,集合属性

背景:为学生的成绩集合属性映射值

<select id="selectAll" resultMap="baseMap2">
    select s.*, c.classname,sc.id scid, sc.score, sc.course, sc.examdate  from student s left join clazz c on s.classid = c.id
                                                                            LEFT JOIN scores sc ON s.id = sc.stuid
</select>

一对多的查询用到了多表联查,查询到的是多条数据。

1. 一对多,嵌套查询

根据查询条件column,通过select查询语句将查询到的结果映射给property属性

<collection property="scores" column="id" select="com.dao.ScoresMapper.selectByStuid"></collection>
标签/属性属性值含义/作用
collection标签为集合属性映射值
propertyscores集合属性
columnid作为查询条件的数据库字段
selectcom.dao.ScoresMapper.selectByStuid调用方法进行查询

2. 一对多,嵌套结果

分别建立对象属性对象属性的属性的映射关系即可
注意:当字段名冲突时,需要起别名

<collection property="scores" ofType="com.bean.Scores">
    <id column="scid" property="id"></id>
    <result column="score" property="score"></result>
    <result column="course" property="course"></result>
    <result column="examdate" property="examdate"></result>
</collection>
标签/属性属性值含义/作用
collection标签为集合属性映射
propertyscores指代集合属性
ofTypecom.bean.Scores集合属性的数据类型
id标签用来设置主键
result标签用来设置其他子段
columnscid数据库字段
propertyid集合属性的属性

四、嵌套查询和嵌套结果的联系和区别

1. 嵌套结果

嵌套结果是嵌套查询结果。

 <resultMap id="baseMap" type="com.bean.Pet">
        <id property="petId" column="petId"></id>
        <result property="petName" column="petName"></result>
        <result property="birthday" column="birthday"></result>
        <result property="typeId" column="typeId"></result>
        <!--javaType是Java数据类型-->
        <association property="pettype" javaType="com.bean.Pettype">
            <id property="typeId" column="typeId"></id>
            <result property="typeName" column="typeName"></result>
        </association>
        <!--ofType是集合里的数据类型-->
        <collection property="healhistorys" ofType="com.bean.Healhistory">
            <id property="id" column="id"></id>
            <result property="petId" column="petId"></result>
            <result property="health" column="health"></result>
            <result property="checkdate" column="checkdate"></result>
        </collection>
    </resultMap>
<select id="selectByPrimaryKey" resultMap="baseMap">
        select p.*, pt.*, h.id,h.petId hpetId, h.health, h.checkdate from pet p
            left join pettype pt on p.typeId = pt.typeId
            left join healhistory h on p.petId = h.petId
            where p.petId = #{petId}
</select>

嵌套结果使用的是多表联查,所有字段都需要查出来,然后根据映射关系一一进行映射。需要注意,当列名相同时,需要起别名来防止字段冲突。

2. 嵌套查询

嵌套查询是嵌套查询语句。

<resultMap id="baseMap2" type="com.bean.Pet">
        <id property="petId" column="petId"></id>
        <result property="petName" column="petName"></result>
        <result property="birthday" column="birthday"></result>
        <result property="typeId" column="typeId"></result>
        <association property="pettype" column="typeId" select="com.dao.PettypeMapper.selectByPrimaryKey"></association>
        <collection property="healhistorys" column="petId" select="com.dao.HealhistoryMapper.selectByPetid"></collection>
</resultMap>
<select id="selectAll" resultMap="baseMap2">
    select * from pet
</select>

嵌套查询使用的是单表查询,对象属性和集合属性通过调用自己的映射的查询方法来获取的。
优点:查询语句简单,与相关子查询相似,但比相关子查询效率高,因为带缓存。
嵌套查询可以添加懒加载,只有使用到对应的属性才会执行相应的查询,否则就不会执行对应的查询语句。

五、 延迟加载/懒加载

作用于嵌套查询

1. 作用

有时候我们在查询数据时,要查询的数据不需要包含对象属性集合属性时,我们该怎么查询?我们可以单独设置一个返回值类型,在获取返回值的时候不添加对象属性或集合属性,这样就不会获取到对象属性和集合属性了。但如果我们不单独添加这样一个返回值类型,而是在原有的返回值类型包含对象属性和集合属性的情况下,如何实现可以在不查询对象属性和集合属性的时候不加载对象属性和集合属性,只有在查询对象属性和集合属性的时候才加载对象属性和集合属性。如果使用的是嵌套查询,这时就可以使用延迟加载。在设置延迟加载/懒加载后,可以极大的提高查询效率。在不需要查询对象属性和集合属性的时候,程序就不会执行对象属性和集合属性相关的查询语句。只有在指定要查询的对象和集合后,才会查询对应的对象和属性。

2. 如何配置懒加载

在MyBatis的主配置文件中为ResultMap映射的对象属性和集合属性一起做配置,添加如下配置语句。
在这里插入图片描述

3. 案例说明

  1. 不添加延迟加载时,如果我们使用嵌套查询查询普通属性时,程序也会查询对象属性集合属性,这样就会导致查询效率较低。

  2. 当我们添加延迟加载后,当我们只查询普通属性时,就不会查询成员属性集合属性
    在这里插入图片描述

  3. 添加延迟加载后,只有当我们查询成员属性集合属性时,才会执行相应的查询语句
    在这里插入图片描述


总结

今天,主要学了ResultMap如何为对象属性和集合属性设置返回值的映射。可以通过嵌套查询和嵌套结果两种方式来实现,这里分别介绍了嵌套查询和嵌套结果用到的标签和属性,主要是明确如何使用。最后还介绍了RresultMap的延迟加载,如何配置,以及延迟加载的优点。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员_动次动次

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值