zoukankan      html  css  js  c++  java
  • MyBatis 支持的扩展点(version:3.2.7)

    从 [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 类型。

  • 相关阅读:
    分享一个文字转成语音的工具,视频配音神器
    生手linux服务器维护常用命令记录
    信不信?各种红包App最后都会整合游戏!App+游戏的变现模式分析
    一个玩游戏的失足青年,转行做游戏开发到教育的痛苦挣扎过程(4)
    免费送!CocosCreator 6.1超级大礼包!
    一个玩游戏的失足青年,转行做游戏开发到教育的痛苦挣扎过程(3)
    【激励视频组件】零编程,即拖即用,妈妈再也不用担心小游戏 SDK 接入了!
    惊天大案!80多款游戏源码被非法倒卖交换!波及数千余人涉案!
    小游戏开发运营挣钱模型之—游戏调优篇(1)
    有个事正在悄然发生,估计谁都无法逆转!只能积极拥抱
  • 原文地址:https://www.cnblogs.com/kevin-yuan/p/7219003.html
Copyright © 2011-2022 走看看