【Mybatis】08 ResultMap、Association、分步查询、懒加载
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、分步查询、懒加载的更多相关文章
- mybatis 详解(八)------ 懒加载
本章我们讲如何通过懒加载来提高mybatis的查询效率. 本章所有代码:http://pan.baidu.com/s/1o8p2Drs 密码:trd6 1.需求:查询订单信息,有时候需要关联查出用户信 ...
- 四十二:数据库之SQLAlchemy之数据查询懒加载技术
懒加载在一对多,或者多对多的时候,如果要获取多的这一部分的数据的时候,通过一个relationship定义好对应关系就可以全部获取,此时获取到的数据是list,但是有时候不想获取全部数据,如果要进行数 ...
- 27.Hibernate-缓存和懒加载.md
目录 1.一级缓存 2.缓存的有效性 3.list和iterator缓存的区别 4.懒加载 4.1get 4.2load 1.一级缓存 Hibernate中一级缓存是Session缓存,有效范围在Se ...
- mybatis中使用懒加载实现一对多复杂查询
1.包结构 2.pom配置 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&qu ...
- mybatis 嵌套查询与懒加载
懒加载:对于页面有很多静态资源的情况下(比如网商购物页面),为了节省用户流量和提高页面性能,可以在用户浏览到当前资源的时候,再对资源进行请求和加载. fetchType="lazy" ...
- MyBatis关联查询和懒加载错误
MyBatis关联查询和懒加载错误 今天在写项目时遇到了个BUG.先说一下背景,前端请求更新生产订单状态,后端从前端接收到生产订单ID进行查询,然后就有问题了. 先看控制台报错: org.apache ...
- MyBatis --- 映射关系【一对一、一对多、多对多】,懒加载机制
映射(多.一)对一的关联关系 1)若只想得到关联对象的id属性,不用关联数据表 2)若希望得到关联对象的其他属性,要关联其数据表 举例: 员工与部门的映射关系为:多对一 1.创建表 员工表 确定其外键 ...
- mybatis使用associaton进行分步查询
Employee类 public class Employee { private Integer id; private String lastName; private String email; ...
- MyBatis加强(1)~myBatis对象关系映射(多对一关系、一对多关系)、延迟/懒加载
一.myBatis对象关系映射(多对一关系.一对多关系) 1.多对一关系: ---例子:多个员工同属于一个部门. (1)myBatis发送 额外SQL: ■ 案例:员工表通过 dept_id 关联 部 ...
- mybatis和hibernate中的懒加载
概念:所谓懒加载就是延时加载,延迟加载.什么时候用懒加载呢,我只能回答要用懒加载的时候就用懒加载.至于为什么要用懒加载呢,就是当我们要访问的数据量过大时,明显用缓存不太合适,因为内存容量有限 ,为了减 ...
随机推荐
- k8s——核心概念篇
服务的分类 有状态 代表应用 nginx apache 优点 对客户端透明,无依赖关系,可以高效实现扩容,迁移 缺点 不能存储数据,需要额外的数据服务支撑 无状态 代表应用 MYSQL Redis 优 ...
- Nacos 版本不一致报错: Request nacos server failed
在做微服务开发中,测试环境使用Nacos没有问题,但是生产环境服务启动一直报错: com.alibaba.nacos.api.exception.NacosException: Request nac ...
- uni-app mpvue wepy websocket的介绍
uni-app 网址:https://uniapp.dcloud.io/ uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS.Android.H5.以 ...
- C#异步编程是怎么回事(番外)
在上一篇通信协议碰到了多线程,阻塞.非阻塞.锁.信号量...,会碰到很多问题.因此我感觉很有必要研究多线程与异步编程. 首先以一个例子开始 我说明一下这个例子. 这是一个演示异步编程的例子. 输入jo ...
- UDP端口探活的那些细节
一 背景 商业客户反馈用categraf的net_response插件配置了udp探测, 遇到报错了,如图 udp是无连接的,无法用建立连接的形式判断端口. 插件最初的设计是需要配置udp的发送字符 ...
- 论文阅读 《Pingmesh: A Large-Scale System for Data Center Network Latency Measurement and Analysis》
背景 在我们内部产品中,一直有关于网络性能数据监控需求,我们之前是直接使用 ping 命令收集结果,每台服务器去 ping (N-1) 台,也就是 N^2 的复杂度,稳定性和性能都存在一些问题,最近打 ...
- nginx访问日志
访客日志 处理日志模块的官网教程 https://nginx.org/en/docs/http/ngx_http_log_module.html 创建nginx访问日志 日志对于程序员很重要,可用于问 ...
- excel计算日期天数和表格冻结首行
excel计算日期天数和表格冻结首行 1.在单元格E35中输入公式DATEDIF(A35.B35."MD")MD表起始日期.结束日期天数差."Y" 时间段中的整 ...
- apollo配置中心从数据库中查询所有的配置及项目
apollo配置中心从数据库中查询所有的配置及项目 需求背景:如果需要从Apollo查询某个配置项做批量的更新替换,如果一个一个找不合适且容易遗漏,需要从底层数据库表中模糊查询来实现. 1.查看apo ...
- discuz论坛个人空间自定义css样式
Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` discuz论坛个人空间自定义css样式 日期:2020- ...