MyBatis是目前非常流行的ORM框架,功能很强大,然而其实现却比较简单、优雅。本文通过代理的方式来看下其实现

方式一:传统API方式

@Test
public void add() throws IOException {
// 1.通过Resources对象加载配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 2.获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream );
// 3.通过SqlSessionFactory对象获取SQLSession对象
SqlSession session = factory.openSession();
User user = new User();
user.setName("dpb");
user.setAge(22);
// dpb.addUser 是映射文件中 namespace的内容加 id的内容,定位要执行的SQL
int count = session.insert("dpb.addUser", user);
System.out.println("影响的行数:"+count);
// 需要显示的提交
session.commit();
session.close();
}

1.怎么加载配置文件的

InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

进入getResourceAsStream方法



小结:

Resources.getResourceAsStream("mybatis-config.xml");这行代码其实很简单,就是通过类加载器加载我们的配置文件,获取到一个InputSream。

扩展知识

getResourceAsStream方法的使用:

1.Class.getResourceAsStream(String path) : path 不以’/'开头时默认是从此类所在的包下取资源,以’/'开头则是从ClassPath根下获取。其只是通过path构造一个绝对路径,最终还是由ClassLoader获取资源

2.Class.getClassLoader.getResourceAsStream(String path) :默认则是从ClassPath根下获取,path不能以’/'开头,最终是由ClassLoader获取资源。

2.怎么获取SqlSessionFactory对象的

// 2.获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder()
.build(inputStream );

源码分析



小结:

通过SqlSessionFactoryBuilder的builder方法获取SqlSessionFactory对象,实际是获取的是DefaultSqlSessionFactory对象,且同时解析了配置文件,并将信息封装到了Configuration对象中。加载配置文件的方式在项目中肯定只需要加载一次。所以在整个项目生命周期中SqlSessionFactory的实例只需要一个,所以此处可以将SqlSessionFactory设计为单例模式。

3.获取SqlSession对象

SqlSession session = factory.openSession();



处理器 说明
SimpleExecutor 就是普通的执行器
ReuseExecutor 执行器会重用预处理语句(prepared statements)
BatchExecutor 批量执行器

同时创建了Transaction对象,该对象有数据库连接对象Connection



创建执行器的过程

小结:

通过openSession()方法获取SqlSession对象,我们获取到了一个DefaultSqlSession实例,不会自动提交事务。实例化了一个执行器,如果我们没有专门指定执行器的类型,那么默认的执行器是SimpleExecutor。且获取了Transaction对象。

4.insert方法执行的过程

int i = session.insert("aaa.addUser", user);
<?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 namespace="aaa">
<insert id="addUser" parameterType="com.sxt.bean.User">
insert into t_user(name,age)values(#{name},#{age})
</insert>
</mapper>

代码跟踪:

添加数据进入DefaultSqlSession方法后调用的还是update方法







回到此处

进入update方法 ==

注意进入的是PreparedStatementHandler==

怎么会进入PreparedStatementHandler的?不是SimpleExecutor处理器,应该进入SimpleStatementHandler吗?

参数在哪动态绑定的呢?

按照相同的方式可以跟踪下查询的方法,代码就在此不贴出来了。

对象 作用
SqlSessionFactory 顶层API,提供SQLSession对象,获取的同时加载配置文件
configuration 封装的有全局配置文件和各个映射文件的相关信息
SqlSession 顶层API,和数据库交互完成增删改查操作
MappedStatement 封装了一条insert|update|delete|select节点信息。
Executor 执行器,调度核心,SimpleExecutor,ReuseExecutor,BatchExecutor.
StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合
BoundSql 封装的有动态SQL及对应的参数信息。
TypeHandler 类型处理器,java类型和数据库字段类型的转换
ResultSetHandler 负责将jdbc的ResultSet的结果和java中List的数据相互转换

方式二:基于Mapper接口方式

@Test
public void add() throws IOException {
// 1.通过Resources对象加载配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 2.获取SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream );
// 3.通过SqlSessionFactory对象获取SQLSession对象
SqlSession session = factory.openSession();
User user = new User();
user.setName("dpb");
user.setAge(22);
//通过Java动态代理自动提供了UserMapper的实现类
UserMapper mapper = session.getMapper(UserMapper.class);
int count = mapper.addUser(user);
System.out.println("影响的行数:"+count);
session.commit();
}

该方式本质上是通过jdk动态代理实现的。

在看源码之前我们自己来简单的实现下看看。

通过jdk动态代理简单实现

bean对象

	private int id;

	private String name;

	private int age;

接口文件

public interface UserMapper {

	public int addUser(User user);

	public int updateById(User user);

	public int deleteById(int id);

	public User queryById(int id);
}

接口实现类

public class UserDao implements UserMapper {

	@Override
public int addUser(User user) { return DBUtils.getInstall().openSession().insert("com.sxt.dao.UserMapper.addUser", user);
} @Override
public int updateById(User user) {
// TODO Auto-generated method stub
return DBUtils.getInstall().openSession().update("com.sxt.dao.UserMapper.updateById", user);
} @Override
public int deleteById(int id) {
// TODO Auto-generated method stub
return DBUtils.getInstall().openSession().delete("com.sxt.dao.UserMapper.deleteById", id);
} @Override
public User queryById(int id) {
// TODO Auto-generated method stub
return DBUtils.getInstall().openSession().selectOne("com.sxt.dao.UserMapper.queryById", id);
}
}

映射文件

注意:namespace和接口全路径名称相同,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 namespace="com.sxt.dao.UserMapper">
<insert id="addUser" parameterType="com.sxt.bean.User">
insert into t_user(name,age)values(#{name},#{age})
</insert> <delete id="deleteById" parameterType="java.lang.Integer">
delete from t_user where id=#{id}
</delete> <update id="updateById" parameterType="com.sxt.bean.User">
update t_user
set name=#{name},age=#{age}
where id=#{id}
</update> <select id="queryById" parameterType="java.lang.Integer"
resultType="com.sxt.bean.User">
select * from t_user where id=#{id}
</select>
</mapper>

目录结构



到此我们发现接口实现UserDao,其实就是个模板,没有特定的内容,这时我们可以将其删掉通过jdk代理的方式实现

测试文件

/**
* 代理方式
*/
@Test
public void test(){
UserMapper mapper = (UserMapper) Proxy.newProxyInstance(UserMapper.class.getClassLoader()
, new Class[]{UserMapper.class},new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(UserMapper.class.getName()+"."+method.getName());
Object id = null;
for (Object object : args) {
System.out.println(object);
id = object;
} // 实现逻辑
return DBUtils.getInstall().openSession().selectOne(UserMapper.class.getName()+"."+method.getName(), id);
}
} );
System.out.println(mapper.queryById(5));
}

测试成功

源码跟踪

源码中看到jdk代理实现的代码。结束~~~

mybatis教程之原理剖析的更多相关文章

  1. iPhone/Mac Objective-C内存管理教程和原理剖析

    http://www.cocoachina.com/bbs/read.php?tid-15963.html 版权声明 此文版权归作者Vince Yuan (vince.yuan#gmail.com)所 ...

  2. Objective-C内存管理教程和原理剖析(四)

    初学Objective-C的朋友都有一个困惑,总觉得对Objective-C的内存管理机制琢磨不透,程 序经常内存泄漏或莫名其妙的崩溃.我在这里总结了自己对Objective-C内存管理机制的研究成果 ...

  3. Objective-C内存管理教程和原理剖析(三)

    初学Objective-C的朋友都有一个困惑,总觉得对Objective-C的内存管理机制琢磨不透,程 序经常内存泄漏或莫名其妙的崩溃.我在这里总结了自己对Objective-C内存管理机制的研究成果 ...

  4. 【MyBatis】MyBatis Tomcat JNDI原理及源码分析

    一. Tomcat JNDI JNDI(java nameing and drectory interface),是一组在Java应用中访问命名和服务的API,所谓命名服务,即将对象和名称联系起来,使 ...

  5. java的加载与执行原理剖析

    到目前为止,我们接触过的重点术语,总结一下: Java体系的技术被划分为三大块: JavaSE:标准版 JavaEE:企业版 JavaME:微型版 安装JDK之后: JDK:java开发工具箱 JRE ...

  6. ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件)

    ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件) Startup Class 1.Startup Constructor(构造函数) 2.Configure ...

  7. ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行

    ASP.NET Core 运行原理剖析1:初始化WebApp模版并运行 核心框架 ASP.NET Core APP 创建与运行 总结 之前两篇文章简析.NET Core 以及与 .NET Framew ...

  8. 【Xamarin挖墙脚系列:Xamarin.IOS机制原理剖析】

    原文:[Xamarin挖墙脚系列:Xamarin.IOS机制原理剖析] [注意:]团队里总是有人反映卸载Xamarin,清理不完全.之前写过如何完全卸载清理剩余的文件.今天写了Windows下的批命令 ...

  9. 【Xamarin 跨平台机制原理剖析】

    原文:[Xamarin 跨平台机制原理剖析] [看了请推荐,推荐满100后,将发补丁地址] Xamarin项目从喊口号到现在,好几个年头了,在内地没有火起来,原因无非有三,1.授权费贵 2.贵 3.原 ...

随机推荐

  1. jdbc随笔

    通过jdbc连接数据库的基本步骤:  导入jar包驱动类  jdbc语法:jdbc:子协议:厂商内容  对于mysql而言:jdbc:mysql://主机地址:端口号/库名               ...

  2. 无线网卡连接网络后共享给本地有线网卡使用(Win10)

    无线网卡连接网络后共享给本地有线网卡使用(Win10) 1. 本文主要目的是介绍地有线网卡共享无线网卡的Wifi信号,该应用场景如下: 当在只有wifi环境下,同时有两台电脑A和B,   A为笔记本: ...

  3. 小白的CTF学习之路1——程序与CPU

    刚刚注册了这个博客园,尽量保持每日一更(*/ω\*) 今天看了po学院的教学视频,了解了程序是什么,如何在CPU当中工作的等各种之前未曾想过的问题,特此记录,以防忘记 首先我们学习程序与CPU之前需要 ...

  4. collection管理程序中不同类别的资源

    在一个计算图中,可以通过collection管理不同类别的资源,如通过tf.add_to_collection函数可以将资源加入一个或多个集合中,然后通过tf.get_collection获取一个集合 ...

  5. leetcode 315. Count of Smaller Numbers After Self 两种思路

    说来惭愧,已经四个月没有切 leetcode 上的题目了. 虽然工作中很少(几乎)没有用到什么高级算法,数据结构,但是我一直坚信 "任何语言都会过时,只有数据结构和算法才能永恒". ...

  6. [solution] JZOJ-5458 质数

    [solution] JZOJ-5458 质数 题面 Description 小X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小X 认为,质数是一切自然数起源的地方. 在小X ...

  7. 前端vue框架 脚手架

    1.安装node.js最新版本2.cmd下输入 1.node -v得到版本号检测是否安装成功 版本号要在6.9以上 2.npm -v 版本号要在3.10以上3.安装脚手架 1.npm install ...

  8. Hessian 使用例子

    一.协议包(数据对象需要实现序列化接口,可以用于服务端接口.客户端调用服务之用) /** * */ package com.junge.demo.protocol.model; import java ...

  9. SDWebImage之SDWebImageDownloaderOperation

    上篇讲了SDWebImageDownloader,从源码分析的过程中,我们知道,实际执行下载任务的是SDWebImageDownloaderOperation,本篇我们来看看SDWebImageDow ...

  10. Android开发工程师文集-提示框,菜单,数据存储,组件篇

    提示框,菜单,数据存储,组件篇 Toast Toast.makeText(context, text, 时间).show(); setDuration();//设置时间 setGravity();// ...