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 自然 ...
随机推荐
- hdu1249 三角形分割平面---递推
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1249 题目大意: 用N个三角形最多可以把平面分成几个区域? 思路: 知道了直线和折线分割平面的情况这 ...
- iOS masonry 不规则tagView布局 并自适应高度
在搜索页面经常会有不规则的tag出现,这种tagView要有点击事件,单个tagView可以设置文字颜色,宽度不固定根据内容自适应,高度固定,数量不固定.总高度就不固定.最近对于masonry的使用又 ...
- 大数据处理架构hadoop
Hadoop简介 Hadoop是Apache软件基金会旗下的一个开源分布式计算平台,为用户提供了系统底层细节透明的分布式基础架构.它是基于java语言开发的,具有很好的跨平台特性,其核心是分布式文件系 ...
- js将一个数组插入另一个数组
var cont =[1,2,3,4]; var res =[4,5,6] for(var i=0;i<res;i++){ cont.push( res.data.list[i]); } con ...
- [HNOI 2011]卡农
Description 题库链接 在集合 \(S=\{1,2,...,n\}\) 中选出 \(m\) 个子集,满足三点性质: 所有选出的 \(m\) 个子集都不能为空. 所有选出的 \(m\) 个子集 ...
- [HNOI 2006]鬼谷子的钱袋
Description 鬼谷子非常聪明,正因为这样,他非常繁忙,经常有各诸侯车的特派员前来向他咨询时政.有一天,他在咸阳游历的时候,朋友告诉他在咸阳最大的拍卖行(聚宝商行)将要举行一场拍卖会,其中有一 ...
- bzoj 1426:收集邮票 求平方的期望
显然如果收集了k天,ans=k*(k+1)/2=(k^2+k)/2.那么现在要求的就是这个东西的期望. 设f[i]表示已有i张邮票,收集到n张的期望次数,g[i]表示已有i张邮票,收集到n张的次数的平 ...
- hdu 4638 树状数组 区间内连续区间的个数(尽可能长)
Group Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
- Java Servlet 笔记1
1. 什么是Servlet. Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序 ...
- Linux编程之内存池的设计与实现(C++98)
假设服务器的硬件资源"充裕",那么提高服务器性能的一个很直接的方法就是空间换时间,即"浪费"服务器的硬件资源,以换取其运行效率.提升服务器性能的一个重要方法就是 ...