Mybatis源码分析--关联表查询及延迟加载(一)
Mybatis提供了关联查询映射的功能。
一、一对一关联
实体类如下:
Users表对应的实体类:
public class User {
private int id;
private String names;
private int age;
private Teacher teacher;
......getXxx和setXxx方法
}
Teacher表对应的实体类:
public class Teacher {
private int id;
private String name;
.....getXxx和setXxx方法
}
Mapper文件中的配置如下:
<mapper namespace="com.tianjunwei.lazy.entity.Users">
<select id="getUser" parameterType="int" resultMap="user">
select * from users,tbl_teacher where users.id=#{id} and users.teacher_id=tbl_teacher.id
</select>
<resultMap type="com.tianjunwei.lazy.entity.User" id="user" >
<id column="id" property="id" javaType="int" jdbcType="INTEGER"></id>
<result column="name" property="names" javaType="string" jdbcType="VARCHAR"/>
<result column="age" property="age" javaType="int" jdbcType="INTEGER"/>
<association property="teacher" javaType="com.tianjunwei.lazy.entity.Teacher"> <!-- fetchType="lazy" -->
<id property="id" column="id"/>
<result property="name" column="name"/>
</association>
</resultMap>
</mapper>
Main函数如下:
public class LazyUser {
public static void main(String [] args){
//mybatis的配置文件
String resource = "learn/mybatis-config.xml";
InputStream is = LazyUser.class.getClassLoader().getResourceAsStream(resource);
//构建sqlSession的工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = sessionFactory.openSession();
String statement = "com.tianjunwei.lazy.entity.Users.getUser";//映射sql的标识字符串
//执行查询返回一个唯一user对象的sql
User user = session.selectOne(statement, 1);
session.commit(true);
System.out.println(user.getNames());
Teacher teacher = user.getTeacher();
System.err.println(teacher.getName());
}
}
这样就可以通过查询获得一对一的User和Teacher的关联数据。
虽然上面的示例帮助我们查询到了User和Teacher的关联数据,但有时候可能我们并不需要关联数据,并且我们是使用一条sql语句通过两个表的联合查询来获得数据的。Mybatis给我们提供了延迟加载的机制,就是当我们不需要Teacher的数据时,并不会给我们查询,当需要Teacher数据时再进行查询,这样有一点不好的地方就是不是一次查询数据,需要多次连接数据库来获取数据。
1、首选需要在Mybatis的配置文件中添加如下配置:
<!-- 打开延迟加载的开关 --> <setting name="lazyLoadingEnabled" value="true" /> <!-- 将积极加载改为消息加载即按需加载 --> <setting name="aggressiveLazyLoading" value="false"/>
2、修改Mapping文件中的内容:
其实就是执行两次sql语句分别获取Users和Teacher中的值
<mapper namespace="com.tianjunwei.lazy.entity.User">
<select id="getById" parameterType="int" resultMap="user">
select * from users where users.id=#{id}
</select>
<select id="getTeacher" resultMap="teacher">
select * from tbl_teacher where id=#{id}
</select>
<resultMap type="com.tianjunwei.lazy.entity.Teacher" id="teacher" >
<id column="id" property="id" javaType="int" jdbcType="INTEGER"></id>
<result column="name" property="name" javaType="string" jdbcType="VARCHAR"/>
</resultMap>
<resultMap type="com.tianjunwei.lazy.entity.User" id="user" >
<id column="id" property="id" javaType="int" jdbcType="INTEGER"></id>
<result column="name" property="names" javaType="string" jdbcType="VARCHAR"/>
<result column="age" property="age" javaType="int" jdbcType="INTEGER"/>
<association property="teacher" javaType="com.tianjunwei.lazy.entity.Teacher" select="com.tianjunwei.lazy.entity.User.getTeacher" column="id"> <!-- fetchType="lazy" -->
<id property="id" column="id"/>
<result property="name" column="name"/>
</association>
</resultMap>
</mapper>
Main函数中的方法还是和原来的一样
public class LazyMain {
public static void main(String [] args){
//mybatis的配置文件
String resource = "learn/mybatis-config.xml";
InputStream is = LazyMain.class.getClassLoader().getResourceAsStream(resource);
//构建sqlSession的工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = sessionFactory.openSession();
String statement = "com.tianjunwei.lazy.entity.User.getById";//映射sql的标识字符串
//执行查询返回一个唯一user对象的sql
User user = session.selectOne(statement, 1);
session.commit(true);
System.out.println(user.getNames());
Teacher teacher = user.getTeacher();
System.err.println(teacher.getName());
}
}
执行过程:从下图你可以看到是执行了两次Sql语句。
当把下面代码注释掉之后,就是我们不需要teacher的数据时
//Teacher teacher = user.getTeacher(); //System.err.println(teacher.getName());
执行结果如下图,就不会执行teacher相关的sql语句,这样就实现了延迟加载的功能。
以上介绍的是一对一的情况,Mapping文件中使用的是association标签
二、一对多关联
我们介绍一下一对多情况
Teacher的实体定义如下:
public class Teacher {
private int id;
private String name;
private List<User> users;
.....getXxx和setXxx方法....
}
Mapper文件中的定义如下,一对多使用的标签是collection,这里我们还是使用延迟加载方式,实现原理就是执行两次SQL,按需执行SQL语句。
<mapper namespace="com.tianjunwei.lazy.entity.Teacher">
<select id="getById" parameterType="int" resultMap="user">
select * from users where users.teacher_id=#{id}
</select>
<select id="getTeacher" resultMap="teacher">
select * from tbl_teacher where id=#{id}
</select>
<resultMap type="com.tianjunwei.lazy.entity.Teacher" id="teacher" >
<id column="id" property="id" javaType="int" jdbcType="INTEGER"></id>
<result column="name" property="name" javaType="string" jdbcType="VARCHAR"/>
<collection property="users" column="id" select="com.tianjunwei.lazy.entity.Teacher.getById" javaType="list">//使用collection标签
</collection>
</resultMap>
<resultMap type="com.tianjunwei.lazy.entity.User" id="user" >
<id column="id" property="id" javaType="int" jdbcType="INTEGER"></id>
<result column="name" property="names" javaType="string" jdbcType="VARCHAR"/>
<result column="age" property="age" javaType="int" jdbcType="INTEGER"/>
</resultMap>
</mapper>
Main函数如下:
public class LazyMainTeacher {
public static void main(String [] args){
//mybatis的配置文件
String resource = "learn/mybatis-config.xml";
InputStream is = LazyMainTeacher.class.getClassLoader().getResourceAsStream(resource);
//构建sqlSession的工厂
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = sessionFactory.openSession();
String statement = "com.tianjunwei.lazy.entity.Teacher.getTeacher";//映射sql的标识字符串
//执行查询返回一个唯一user对象的sql
Teacher teacher = (Teacher) session.selectList(statement, 1).get(0);
session.commit(true);
System.out.println(teacher.getName());
List<User> users = teacher.getUsers();
System.err.println(users.get(3).getAge());
}
}
运行结果:可以看到确实是执行两次SQL语句
Mybatis源码分析--关联表查询及延迟加载(一)的更多相关文章
- Mybatis源码分析--关联表查询及延迟加载原理(二)
在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...
- MyBatis源码分析(4)—— Cache构建以及应用
@(MyBatis)[Cache] MyBatis源码分析--Cache构建以及应用 SqlSession使用缓存流程 如果开启了二级缓存,而Executor会使用CachingExecutor来装饰 ...
- MyBatis 源码分析系列文章导读
1.本文速览 本篇文章是我为接下来的 MyBatis 源码分析系列文章写的一个导读文章.本篇文章从 MyBatis 是什么(what),为什么要使用(why),以及如何使用(how)等三个角度进行了说 ...
- Mybatis源码分析之Cache二级缓存原理 (五)
一:Cache类的介绍 讲解缓存之前我们需要先了解一下Cache接口以及实现MyBatis定义了一个org.apache.ibatis.cache.Cache接口作为其Cache提供者的SPI(Ser ...
- MyBatis源码分析-SQL语句执行的完整流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析之环境准备篇
前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...
- Mybatis源码分析-BaseExecutor
根据前文Mybatis源码分析-SqlSessionTemplate的简单分析,对于SqlSession的CURD操作都需要经过Executor接口的update/query方法,本文将分析下Base ...
- 【MyBatis源码分析】环境准备
前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...
- MyBatis 源码分析 - 缓存原理
1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力.作为一个重要的组件,MyBatis 自然 ...
随机推荐
- append()/extend()/insert()/remove()/del/pop()/slice列表分片
member = ['小甲鱼', 88, '黑夜', 90, '迷途', 85, '怡静', 90, '秋舞斜阳', 88] member.append('字符串')#在列表结尾处增加字符串 memb ...
- Docker 基础技术之 Linux namespace 源码分析
上篇我们从进程 clone 的角度,结合代码简单分析了 Linux 提供的 6 种 namespace,本篇从源码上进一步分析 Linux namespace,让你对 Docker namespace ...
- window下编辑了脚本文件linux报如下错误
首先vi :set ff 查看文件类型 接着 下载dos2unix root用户下yum -y install dos2unix 然后 dos2unix 文件.sh 转换格式 接着在正常启动即可
- Centos下安装 .net Core运行程序
首先要进行更新下镜像文件 sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc sudo sh -c 'echo -e ...
- U盘分区后合并
1.首先把你的U盘插在电脑上,点击开始→所有程序→附件→命令提示符(前面这步骤也可以直接用Win+R组合键打开"运行",之后输入cmd也可打开命令提示符). 2.然后在命令提示窗口 ...
- UEditor Golang上传图片与附件
UEditor图片与附件上传官方只支持ASP.ASP.NET.JSP.PHP四种语言版本,Golang就不在其中.因为自己开发系统的需要,我照着UEditor服务器端的接口自己实现了一个Golang版 ...
- [LeetCode] Toeplitz Matrix 托普利兹矩阵
A matrix is Toeplitz if every diagonal from top-left to bottom-right has the same element. Now given ...
- echarts.js--前端可视化数据图形
ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上, 兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等 ...
- [ Java学习基础 ] 浅析Java方法调用
先看一个示例,读者可先自行阅读判断输出结果: public class TestClass { private static void testMethod(){ System.out.printl ...
- 计蒜客NOIP模拟赛D2T3 数三角形
刚刚上高中的洁洁在学习组合数学的过程中遇到一道麻烦的题目,她希望你能帮助她解决.给定一张无向完全图 G,其中大部分边被染成蓝色,但也有一些边被染成红色或者绿色.现在,洁洁需要给这张图的多样性进行打分. ...