ResultMap自定义结果集

可以把查询返回的结果集封装成复杂的JavaBean对象

原来的ResultType属性,只能把查询到的结果集转换为简单的JavaBean

什么是简单的JavaBean对象?

- 不具有JavaBean和集合类型属性的对象

- 也就是不能建立ORM的多表关联映射

问题的引入:

如果字段标识符和数据表不一致,

例如实体类的user的密码字段,现在更改为pwd

数据表的字段依然为user_password

我们查询这个结果看看

所有的密码字段接受失败

那么,该如何解决这个问题?

方案一,在SQL语句中给这个字段起别名

再次测试,这个数据又能获取到了

但是这样的解决方案并不优雅

Mybatis提供了一个解决方案,使用ResultMap对字段标识进行映射绑定

测试结果,可行

一对一关系案例:

创建数据表

锁表 & 钥匙【一把锁就配一把钥匙】

CREATE TABLE t_lock(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(50) ); CREATE TABLE t_key(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(50),
`lock_id` INT,
FOREIGN KEY(`lock_id`) REFERENCES t_lock(`id`)
);

添加数据

INSERT INTO t_lock(`name`)
VALUES
('阿里巴巴'),
('联想'),
('华为'); INSERT INTO t_key(`name`,`lock_id`)
VALUES
('马云',1),
('任正非',2),
('柳传志',3);

【写反了,唉就这样把】

创建ORM实体类

锁类

package cn.dai.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; /**
* @author ArkD42
* @file Mybatis
* @create 2020 - 05 - 29 - 13:30
*/ @Data
@AllArgsConstructor
@NoArgsConstructor
public class Lock { private Integer id;
private String name;
}

钥匙类

package cn.dai.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; /**
* @author ArkD42
* @file Mybatis
* @create 2020 - 05 - 29 - 13:32
*/ @Data
@NoArgsConstructor
@AllArgsConstructor
public class Key { private Integer id;
private String name; // 注意这个设置的外键是来自这个锁对象的属性
private Lock lock; }

映射器【KeyMaper.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接口名称-->
<mapper namespace="cn.dai.mapper.KeyMapper"> <select id="queryKeyById" resultType="cn.dai.pojo.Key" parameterType="java.lang.Integer">
SELECT * FROM t_key WHERE id = #{id}
</select> </mapper>

注意!在这里采用的结果集类型,先看看结果如何

测试类

    @Test
public void sqlTest6(){
logger.info("- - - - TESTING - - - -");
SqlSession sqlSession = MybatisUtil.getSqlSession(true);
KeyMapper keyMapper = sqlSession.getMapper(KeyMapper.class); Key key = keyMapper.queryKeyById(2);
System.out.println(key); sqlSession.close();
}

结果:我们对应的锁类无法获取

我们需要一个关联查询来实现

首先从SQL语句实现

【查询钥匙表关联锁表,一起获取】

        SELECT
t_key.*,t_lock.name lock_name
FROM
t_key LEFT JOIN t_lock
ON
t_key.lock_id = t_lock.id
WHERE
t_key.id = #{id}

【就算是这样,没有类型匹配,返回的结果还是和上面一样,这里不展示了】

【留意SELECT子句筛选的字段】

所以需要通过结果集映射标签实现一些类型的绑定

使用默认的result标签处理

然后使用我们的结果集映射标签实现关联处理

<?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接口名称-->
<mapper namespace="cn.dai.mapper.KeyMapper"> <!--
id 设置这个结果集映射标签的标识,
type 设置需要转换出来的实体类对象的全限定类名
-->
<resultMap id="key" type="key"> <!-- id标签负责 转换主键列 -> 实体类的属性 -->
<id column="id" property="id"/>
<!-- 非主键列 转换给 实体类属性 -->
<result column="name" property="name"/>
<!-- 一般匹配的字段不需要显示的写出来,因为是默认的了 --> <!--
property 对应的是实体类的属性
column 对应的是数据表的列
-->
<result column="lock_id" property="lock.id" />
<result column="lock_name" property="lock.name" /> </resultMap> <!-- 这里的结果集映射就对应上面设置的id -->
<select id="queryKeyById" resultMap="key" parameterType="int">
SELECT
t_key.*,t_lock.name lock_name
FROM
t_key LEFT JOIN t_lock
ON
t_key.lock_id = t_lock.id
WHERE
t_key.id = #{id}
</select> </mapper>

测试结果

千万要注意,要实现这个锁的名称的输出,就要留意上面的SELECT 筛选的字段

可以通过别名映射实现一些实体类的绑定

在这里是因为左外链接,所以可以看到,钥匙表是没有写这个表名的

或者使用Association标签实现映射

在结果集中设置关联映射标签,绑定属性标识和所对应的类型

其次声明关联表的属性映射

       <association property="lock" javaType="cn.dai.pojo.Lock">
<id column="lock_id" property="id"/>
<result column="lock_name" property="name" />
</association>

Association定义分布查询

什么意思?

可以通过一个查询得到子对象

分两种加载,立即加载和懒加载

一张表可能存在50多列,其中主要常用的是最前面的6列

后面的44列不一定马上需要,所以我们的查询应该拆分成两次查询

我们声明一个两步查询的方法

Key queryKeyByIdForTwoStep(Integer id);

对副表的二次查询在锁表中编写

package cn.dai.mapper;

import cn.dai.pojo.Lock;

/**
* @author ArkD42
* @file Mybatis
* @create 2020 - 05 - 30 - 11:59
*/
public interface LockMapper { Lock queryLockById(Integer id); }

锁表的映射器

<?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接口名称-->
<mapper namespace="cn.dai.mapper.LockMapper"> <select id="queryLockById" resultType="cn.dai.pojo.Lock" >
select * from t_lock where id = #{id}
</select> </mapper>

钥匙表的映射器

    <resultMap id="key2" type="cn.dai.pojo.Key">

        <id column="id" property="id"/>
<result column="name" property="name"/> <!--
select 调用另外一个映射器的查询方法,来获取对象的结果
column 把这钥匙表的查询SQL的字段结果返回给这个关联查询调用【就是那个查询的参数】 -->
<association
property="lock"
javaType="cn.dai.pojo.Lock"
select="cn.dai.mapper.LockMapper.queryLockById"
column="lock_id"
/> </resultMap> <select id="queryKeyByIdForTwoStep" resultMap="key2" parameterType="int">
SELECT
id,name,lock_id
FROM
t_key
WHERE
t_key.id = #{id}
</select>

测试结果

可以看到这样查询分了两次执行,并且把字段的参数传递给下一个查询的使用

开启懒加载查询

即延迟加载,减少非必要性的查询

优化数据库性能,需要在全局配置中开启

        <!-- 开启懒加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>

    @Test
public void sqlTest7(){
logger.info("- - - - TESTING - - - -");
SqlSession sqlSession = MybatisUtil.getSqlSession(true);
KeyMapper keyMapper = sqlSession.getMapper(KeyMapper.class); Key key = keyMapper.queryKeyByIdForTwoStep(2); //System.out.println(key); //开启懒加载是什么效果?如果我们不调用附表的信息,第二个查询是不会调用的
System.out.println(key.getName()); sqlSession.close();
}

结果

实际作用远不止这些,详见官方文档:

https://mybatis.org/mybatis-3/zh/sqlmap-xml.html

【Mybatis】08 ResultMap、Association、分步查询、懒加载的更多相关文章

  1. mybatis 详解(八)------ 懒加载

    本章我们讲如何通过懒加载来提高mybatis的查询效率. 本章所有代码:http://pan.baidu.com/s/1o8p2Drs 密码:trd6 1.需求:查询订单信息,有时候需要关联查出用户信 ...

  2. 四十二:数据库之SQLAlchemy之数据查询懒加载技术

    懒加载在一对多,或者多对多的时候,如果要获取多的这一部分的数据的时候,通过一个relationship定义好对应关系就可以全部获取,此时获取到的数据是list,但是有时候不想获取全部数据,如果要进行数 ...

  3. 27.Hibernate-缓存和懒加载.md

    目录 1.一级缓存 2.缓存的有效性 3.list和iterator缓存的区别 4.懒加载 4.1get 4.2load 1.一级缓存 Hibernate中一级缓存是Session缓存,有效范围在Se ...

  4. mybatis中使用懒加载实现一对多复杂查询

    1.包结构 2.pom配置 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&qu ...

  5. mybatis 嵌套查询与懒加载

    懒加载:对于页面有很多静态资源的情况下(比如网商购物页面),为了节省用户流量和提高页面性能,可以在用户浏览到当前资源的时候,再对资源进行请求和加载. fetchType="lazy" ...

  6. MyBatis关联查询和懒加载错误

    MyBatis关联查询和懒加载错误 今天在写项目时遇到了个BUG.先说一下背景,前端请求更新生产订单状态,后端从前端接收到生产订单ID进行查询,然后就有问题了. 先看控制台报错: org.apache ...

  7. MyBatis --- 映射关系【一对一、一对多、多对多】,懒加载机制

    映射(多.一)对一的关联关系 1)若只想得到关联对象的id属性,不用关联数据表 2)若希望得到关联对象的其他属性,要关联其数据表 举例: 员工与部门的映射关系为:多对一 1.创建表 员工表 确定其外键 ...

  8. mybatis使用associaton进行分步查询

    Employee类 public class Employee { private Integer id; private String lastName; private String email; ...

  9. MyBatis加强(1)~myBatis对象关系映射(多对一关系、一对多关系)、延迟/懒加载

    一.myBatis对象关系映射(多对一关系.一对多关系) 1.多对一关系: ---例子:多个员工同属于一个部门. (1)myBatis发送 额外SQL: ■ 案例:员工表通过 dept_id 关联 部 ...

  10. mybatis和hibernate中的懒加载

    概念:所谓懒加载就是延时加载,延迟加载.什么时候用懒加载呢,我只能回答要用懒加载的时候就用懒加载.至于为什么要用懒加载呢,就是当我们要访问的数据量过大时,明显用缓存不太合适,因为内存容量有限 ,为了减 ...

随机推荐

  1. vmware 和 hyper-v不兼容,此主机不支持64位客户机操作系统

    在控制面板中关闭hyper-v功能后,仍然提示此主机不支持64位客户机操作系统. 解决方法: 需要在开始按钮 - 右键  -打开Windows PowerShell(管理员). 输入: bcdedit ...

  2. 为什么boolean 类型的字段不建议使用is开头?

    对于非boolean类型的参数,getter和setter方法命名的规范是以get和set开头 对于boolean类型的参数,setter方法是以set开头,但是getter方法命名的规范是以is开头 ...

  3. restful接口返回JSONObject和父类抽象实现类设计,请求头获取sign和支付宝RSA签名验签工具类方法

    restful接口返回JSONObject和父类抽象实现类设计,请求头获取sign和支付宝RSA签名验签工具类方法 1.JSONObject可以通用数据的灵活性,类似Map数据,数据字段不清晰.具体返 ...

  4. maven依赖关系及打包及阿里云仓库地址

    https://developer.aliyun.com/mvn/search 阿里云仓库地址,可以搜索 <repositories> <repository> <id& ...

  5. Asp.net Core Flurl.Http 结合IHttpClientFactory管理HttpClient生命周期

    Asp.net Core, 在我用过的多种Http REST 客户端: RestSharp WebApiClient Refit Flurl 中,Flurl可以说是最符合我口味的,用起来那可真的顺滑无 ...

  6. Linux中的环境变量PS1,打造你的专属终端

    文章目录 介绍 PS1的格式 设置字体样式 举例 小建议 进阶 介绍 好看的终端是怎么做的呢?通过PS1这个环境变量! PS1的格式 PS1='[\u@\h \w]\$ ' 样式: 解释: [是普通字 ...

  7. linux 下新建显示器分辨率

    1. 输入cvt 1920 1080 (假设需要添加的分辨率为1920x1080), 获取Mode Line # 1920x1080 59.96 Hz (CVT 2.07M9) hsync: 67.1 ...

  8. Linux 提权-Docker 容器

    本文通过 Google 翻译 Docker Breakout – Linux Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校正及个别注释补充. ...

  9. JS中this的几种指向

    这些this的指向,是当我们调用函数的时候确定的.调用方式的不同决定了this的指向不同一般指向我们的调用者.普通函数调用          window.定时器函数             wind ...

  10. 谈谈你对 Vue 生命周期的理解?

    生命周期是什么? Vue 实例有一个完整的生命周期,也就是从 开始创建.初始化数据.编译模版.挂载 Dom -> 渲染.更新 -> 渲染.卸载等一系列过程,我们称这是 Vue 的生命周期. ...