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. react组件传值(props[只读属性]) 函数组件

    组件间传值,在React中是通过只读属性 props 来完成数据传递的. props:接受任意的入参,并返回用于描述页面展示内容的 React 元素. function Cmp1(props) { r ...

  2. 后端给前端rtmp和flv直播 播放方法

    const suffixal = this.videoObj.videoServer .split('?')[0] .split('.') .pop() var router = this.$rout ...

  3. kettle从入门到精通 第三十九课 kettle 增量同步(日级)

    1.上一课我们学习了在数据量大的情况下的分页全量同步示例,本次我们一起学习下kettle 增量全量同步.有些业务场景不需要实时数据,比如统计t-1日的销售业绩情况等.   2.kettle增量全量同步 ...

  4. OpenSSL生成加密证书.cer和.pfx

    linux自带openssl,所以在linux平台操作. 先输入: openssl 再输入: genrsa -out private-rsa.key 1024 生成私钥,无密码保护的私钥. 输入: r ...

  5. redis缓存详解(从入门到精通)

    引言 Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(l ...

  6. react的类组件的ts写法

    react的类组件的ts写法,声明的变量,props和state的写法 import React, { PureComponent } from 'react'; interface Iprops { ...

  7. re.search()用法详解

    re.search() 是 Python 的正则表达式库 re 中的一个方法,用于在字符串中搜索与正则表达式模式匹配的第一个位置,并返回一个匹配对象.如果没有找到匹配项,则返回 None. 以下是 r ...

  8. RuoYi-Cloud从配置到运行

    前期准备工作 若依微服务版(RuoYi-Cloud)代码下载:https://gitee.com/y_project/RuoYi-Cloud 注册中心(nacos)下载:https://www.ali ...

  9. VulnHub_DC-5渗透流程

    DC-5 主机探测 nmap 192.168.157.0/24 访问网站 探测网站得知是Nginx 目录扫描 在Contact处可以提交东西,抓个包,发现在thankyou.php界面时间年份会变,应 ...

  10. Kolla-ansible部署openStack

    目录 Kolla-ansible部署openStack 1. 简介 2. 环境准备 3. 部署 3.1 基础环境配置 3.1.1 配置主机名,所有节点操作,这里以openstack01为例 3.1.2 ...