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

  • 相关阅读:
    ZOJ 1649: Rescue(BFS)
    UVA
    hdu2458:Kindergarten (最大独立集)
    hdu3829:Cat VS Dog (最大独立集)
    Java 泛型
    request.getParameter() 和request.getAttribute() 区别
    Solr版本安装部署指南
    java.sql.SQLException: Incorrect string value: 'xE6x88x91xE7x9Ax84...' for column 'groupName'
    Incorrect string value: 'xF0x9Fx98x84xF0x9F
    java里面byte数组和String字符串怎么转换
  • 原文地址:https://www.cnblogs.com/kevin-yuan/p/7219003.html
Copyright © 2011-2022 走看看