从 [MyBatis 原码解析(version:3.2.7)] 中,我们得知,MyBatis去执行SQL都是通过 DefaultSqlSession 中的工具方法去执行的。

那么问题来了,MyBatis 是怎么构造 DefaultSqlSession 的?

通过查看源码,得知 MyBatis 是通过 DefaultSqlSessionFactory 来构造 DefaultSqlSession 的。

DefaultSqlSessionFactory#openSessionFromDataSource(ExecutorType, TransactionIsolationLevel, boolean)

/**
* @param ExecutorType 执行器的类型。MyBatis中提供了三种执行器:SIMPLE, REUSE, BATCH。默认的是 SIMPLE
* @param TransactionIsolationLevel 事务隔离级别
* @param autoCommit 是否自动提交事务
*/
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); // 通过 Environment 获取事务工厂 TransactionFactory。没有指定Environment,则使用 ManagedTransactionFactory
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); // 从 TransactionFactory 中获取一个 Transaction
final Executor executor = configuration.newExecutor(tx, execType); // 从 Configuration 中获取一个新的 Executor。(Configuration 对应的是 mybatis-config.xml 中的配置)
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}

重点看一下 Configuration#newExecutor(Transaction transaction, ExecutorType executorType)

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType; // 默认使用 SimpleExecutor
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction); // 使用 BatchExecutor
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction); // 使用 ReuseExecutor
} else {
executor = new SimpleExecutor(this, transaction); // 默认使用 SimpleExecutor
}
if (cacheEnabled) {
executor = new CachingExecutor(executor); // 使用 CachingExecutor
}
executor = (Executor) interceptorChain.pluginAll(executor); // 执行所有的MyBatis拦截器,并返回 Executor
return executor;
}

至此,我们找到了MyBatis的一个扩展点——拦截器interceptor。

MyBatis Inteceptor是使用JDK的动态代理来实现的,所以它只能对接口进行拦截。

里面两个很重要的注解是:@Intercepts、@Signature
@Intercepts : 标记要拦截的方法签名
@Signature : 方法签名,唯一的标记一个接口的方法

通过查看源码,我们还可以知道,MyBatis所有的代理拦截都是通过 InterceptorChain.pluginAll(Object target) 来实现的。
至此,我们得到下图:

通过上图可知,Mybatis支持对 Executor 、 StatementHandler 、 ResultSetHandler 和 PameterHandler 进行拦截,也就是说会对这4种对象进行代理。

Executor                : 作用是执行SQL语句(所有的sql),并且对事务、缓存等提供统一接口。(在这一层上做拦截的权限会更大)
StatementHandler : 作用是对 statement 进行预处理,并且提供统一的原子的增、删、改、查接口。(如果要在SQL执行前进行拦截的话,拦截这里就可以了)
ResultSetHandler  : 作用是对返回结果ResultSet进行处理。
PameterHandler    : 作用是对参数进行赋值。

附:

对 TypeHandler 进行扩展:http://mp.weixin.qq.com/s/GLb_-dLVAWYb6-_GWGIF8w
解决问题:
  从SqlServer中取数据,遇到很多列都是Numeric(10,2)类型,指的是字段是数字型,长度为10,小数为两位。Mybatis默认的BigDecimalTypeHandler取到后,都默认变成4位小数,不够的补了0。而上层的要求是,拿到的和数字相关的数据都要2位小数。这时,可以自定义一个 TypeHandler 进行统一处理

TypeHandler 的作用:无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器 TypeHandler 将获取的值以合适的方式转换成 Java 类型。

MyBatis 支持的扩展点(version:3.2.7)的更多相关文章

  1. mybatis支持jdk8等localdate类型

    大家知道,在实体Entity里面,可以使用java.sql.Date.java.sql.Timestamp.java.util.Date来映射到数据库的date.timestamp.datetime等 ...

  2. EntityFramework中支持BulkInsert扩展

    EntityFramework中支持BulkInsert扩展 本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 前言 很显然,你应该不至于使用 Ent ...

  3. yum 安装apache php 使php支持memcached扩展

    在公司上新项目的时候,无论生产环境还是测试环境,都会让运维安装php 环境(lamp/lnmp),并让php支持memcached 的扩展.这里搭建php环境其实主要就是搭建apache 和php.m ...

  4. 【03】Chrome提示印象笔记剪藏插件"已停用不支持的扩展程序"怎么办?

    [03] Chrome提示印象笔记剪藏插件"已停用不支持的扩展程序"怎么办? 刚好也遇上了这个问题,百度了一下,以下是解决方法,亲测可行: 1.首先把需要安装的第三方插件,后缀.c ...

  5. .net core 3.0 Signalr - 04 使用Redis做底板来支持横向扩展

    在实际的系统中,可能需要多台机器部署;然而,Signalr的连接信息是跟站点走的,举个例子 推送系统部署了A.B两个服务器,张三访问A服务器,李四访问B服务器,当张三通过A服务器向李四推送的时候,A服 ...

  6. 使Jackson和Mybatis支持JSR310标准

    1.首先要确保Jackson和Mybatis正确地整合进项目了 2.添加额外的依赖 <dependency> <groupId>org.mybatis</groupId& ...

  7. 记一次 IDEA mybatis.generator 自定义扩展插件

    在使用 idea mybatis.generator 生成的代码,遇到 生成的代码很多重复的地方, 虽然代码是生成的,我们也不应该允许重复的代码出现,因为这些代码后期都要来手动维护. 对于生成时间戳注 ...

  8. springboot + mybatis 支持oracle和mysql切换含源码

    1.springboot 启动类加入bean 如下 // DatabaseIdProvider元素主要是为了支持不同的数据库@Beanpublic DatabaseIdProvider getData ...

  9. 全网唯一开源java开发的支持高扩展,高性能的Mqtt集群broker!

    SMQTT是一款开源的MQTT消息代理Broker, SMQTT基于Netty开发,底层采用Reactor3反应堆模型,支持单机部署,支持容器化部署,具备低延迟,高吞吐量,支持百万TCP连接,同时支持 ...

随机推荐

  1. logback.xml配置文件详解

    越是老司机越会对日志重视. 如下配置实现了 1.日志文件使用相对路径输出. 2.从日期与文件大小两个纬度分割. 3.特定包与类的日志输出 ** 当存在多个name相同的logger时,逻辑不是很清楚 ...

  2. .gitignore不生效解决办法

    .gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的.那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提 ...

  3. oracleinsert的时候返回插入的ID

    //---------------- 声明部分 ---------------- create or replace package Pro_Test_User is PROCEDURE Ins_Te ...

  4. 解决Android 7.0 App内切换语言不生效的问题

    Android7.0及以前版本,Configuration中的语言相当于是App的全局设置: public static void changeAppLanguage(Context context, ...

  5. 关于源码输出,浏览器不解析Html标签

    有时候根据需要我们需要看到浏览器上源码效果如: 但是我如果在html中输入 <a href = 'http://www.baidu.com'>百度</a>那么问题来了,总是显示 ...

  6. FaceAlignment blog

    https://blog.csdn.net/app_12062011/article/category/7574425 https://www.jianshu.com/p/e4b9317a817f

  7. Solr系列五:solr搜索详解(solr搜索流程介绍、查询语法及解析器详解)

    一.solr搜索流程介绍 1. 前面我们已经学习过Lucene搜索的流程,让我们再来回顾一下 流程说明: 首先获取用户输入的查询串,使用查询解析器QueryParser解析查询串生成查询对象Query ...

  8. Lua------------------unity与lua的热更新

    [Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘终结篇:UniLua热更新完全解读 标签: 游戏开发游戏解决方案用户体验unity3d 2014-10-18 23:23 7680人阅读 ...

  9. 远程桌面连接工具 Remote Desktop Manager 9.1.2.0 Enterprise 多国语言绿色版附注册码 简单使用

    1:修改成中文简体 2: 注册破解  (记得一定要先断网)   admin admin@admin.com 31GKI-OK1HY-59H35-Y8GPB-8WDY6 3 : 创建连接   搞定

  10. IDEA VS 快捷键 大全

    [参考]IntelliJ IDEA 常用 黄金 快捷键  总结 不断更新     一.VS常用快捷键 (01).快速插入foreach.try等循环:Tab + Tab; (02).回到光标前一位置: ...