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源码分析--关联表查询及延迟加载(一)的更多相关文章

  1. Mybatis源码分析--关联表查询及延迟加载原理(二)

    在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...

  2. MyBatis源码分析(4)—— Cache构建以及应用

    @(MyBatis)[Cache] MyBatis源码分析--Cache构建以及应用 SqlSession使用缓存流程 如果开启了二级缓存,而Executor会使用CachingExecutor来装饰 ...

  3. MyBatis 源码分析系列文章导读

    1.本文速览 本篇文章是我为接下来的 MyBatis 源码分析系列文章写的一个导读文章.本篇文章从 MyBatis 是什么(what),为什么要使用(why),以及如何使用(how)等三个角度进行了说 ...

  4. Mybatis源码分析之Cache二级缓存原理 (五)

    一:Cache类的介绍 讲解缓存之前我们需要先了解一下Cache接口以及实现MyBatis定义了一个org.apache.ibatis.cache.Cache接口作为其Cache提供者的SPI(Ser ...

  5. MyBatis源码分析-SQL语句执行的完整流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  6. MyBatis源码分析之环境准备篇

    前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...

  7. Mybatis源码分析-BaseExecutor

    根据前文Mybatis源码分析-SqlSessionTemplate的简单分析,对于SqlSession的CURD操作都需要经过Executor接口的update/query方法,本文将分析下Base ...

  8. 【MyBatis源码分析】环境准备

    前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...

  9. MyBatis 源码分析 - 缓存原理

    1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力.作为一个重要的组件,MyBatis 自然 ...

随机推荐

  1. hdu1249 三角形分割平面---递推

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1249 题目大意: 用N个三角形最多可以把平面分成几个区域? 思路: 知道了直线和折线分割平面的情况这 ...

  2. iOS masonry 不规则tagView布局 并自适应高度

    在搜索页面经常会有不规则的tag出现,这种tagView要有点击事件,单个tagView可以设置文字颜色,宽度不固定根据内容自适应,高度固定,数量不固定.总高度就不固定.最近对于masonry的使用又 ...

  3. 大数据处理架构hadoop

    Hadoop简介 Hadoop是Apache软件基金会旗下的一个开源分布式计算平台,为用户提供了系统底层细节透明的分布式基础架构.它是基于java语言开发的,具有很好的跨平台特性,其核心是分布式文件系 ...

  4. 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 ...

  5. [HNOI 2011]卡农

    Description 题库链接 在集合 \(S=\{1,2,...,n\}\) 中选出 \(m\) 个子集,满足三点性质: 所有选出的 \(m\) 个子集都不能为空. 所有选出的 \(m\) 个子集 ...

  6. [HNOI 2006]鬼谷子的钱袋

    Description 鬼谷子非常聪明,正因为这样,他非常繁忙,经常有各诸侯车的特派员前来向他咨询时政.有一天,他在咸阳游历的时候,朋友告诉他在咸阳最大的拍卖行(聚宝商行)将要举行一场拍卖会,其中有一 ...

  7. bzoj 1426:收集邮票 求平方的期望

    显然如果收集了k天,ans=k*(k+1)/2=(k^2+k)/2.那么现在要求的就是这个东西的期望. 设f[i]表示已有i张邮票,收集到n张的期望次数,g[i]表示已有i张邮票,收集到n张的次数的平 ...

  8. hdu 4638 树状数组 区间内连续区间的个数(尽可能长)

    Group Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  9. Java Servlet 笔记1

    1. 什么是Servlet. Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序 ...

  10. Linux编程之内存池的设计与实现(C++98)

    假设服务器的硬件资源"充裕",那么提高服务器性能的一个很直接的方法就是空间换时间,即"浪费"服务器的硬件资源,以换取其运行效率.提升服务器性能的一个重要方法就是 ...