zoukankan      html  css  js  c++  java
  • Mybatis笔记

    思考 https://www.zhihu.com/question/270387939/answer/360487647
    https://blog.csdn.net/isea533/category_2092001.html

    Mybatis 客户端调用过程

    // 加载配置
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    // 构建核心工厂
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "development");
    // 创建会话
    SqlSession session = sqlSessionFactory.openSession();
    // 动态代理,生成Dao层接口对象
    IUser userMapper = session.getMapper(IUser.class);
    

    SqlSessionFactoryBuilder

    顾名思义,这是SqlSessionFactory的建造者类;内部通过XmlConfigBuilder去解析mybatis的config配置xml文件得到Configuration对象。

    // 构造器
    private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
        super(new Configuration()); // 创建Configuration对象
        ErrorContext.instance().resource("SQL Mapper Configuration");
        this.configuration.setVariables(props);
        this.parsed = false;
        this.environment = environment;
        this.parser = parser;
    }
    

    XMLConfigBuilder中解析config.xml文件方法的具体内容:

    private void parseConfiguration(XNode root) {
        try {
          //issue #117 read properties first
          propertiesElement(root.evalNode("properties"));
          Properties settings = settingsAsProperties(root.evalNode("settings"));
          loadCustomVfs(settings);
          loadCustomLogImpl(settings);
          typeAliasesElement(root.evalNode("typeAliases"));
          pluginElement(root.evalNode("plugins"));
          objectFactoryElement(root.evalNode("objectFactory"));
          objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
          reflectorFactoryElement(root.evalNode("reflectorFactory"));
          settingsElement(settings);
          // read it after objectFactory and objectWrapperFactory issue #631
          environmentsElement(root.evalNode("environments"));
          databaseIdProviderElement(root.evalNode("databaseIdProvider"));
          typeHandlerElement(root.evalNode("typeHandlers"));
          mapperElement(root.evalNode("mappers"));
        } catch (Exception e) {
          throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
        }
      }
    

    详细的Configuration配置及属性含义可以参考官网 https://mybatis.org/mybatis-3/zh/configuration.html

    XmlConfigBuilder内部又会通过XMLMapperBuilder类去解析mapper.xml文件,并补将结果存入Configuration对象中(此处省略)。

      private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;
        try {
          final Environment environment = configuration.getEnvironment();
          final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
          tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
          final Executor executor = configuration.newExecutor(tx, execType);
          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();
        }
      }
    

    上面是SqlSessionFactory创建sqlSesion的过程,因此一旦Configuration对象确定了,SqlSession也就可以生产出来了,根据传参execType选择使用的哪个执行器Executor。

    Executor

    执行器 定义了如query,update,commit,rollback等数据库操作的基本方法。
    Executor是DefaultSqlSession的成员变量,在openSession时创建,可以指定使用哪个Executor的实现类,未指定默认使用ExecutorType.SIMPLE;也可以通过配置settings.defaultExecutorType属性来指定默认执行器

    CachingExecutor:二级缓存执行器(settings.cacheEnabled未配置情况下,默认开启);使用装饰器模式,内部引用了BaseExecutor。
    BaseExecutor:是SimpleExecutor,ReuseExecutor,BatchExecutor三个执行器的抽象父类。

    Plugins

    MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
    Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
    ParameterHandler (getParameterObject, setParameters)
    ResultSetHandler (handleResultSets, handleOutputParameters)
    StatementHandler (prepare, parameterize, batch, update, query)

    通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。

    @Intercepts({@Signature(
      type= Executor.class,
      method = "update",
      args = {MappedStatement.class,Object.class})})
    public class ExamplePlugin implements Interceptor {
      private Properties properties = new Properties();
      public Object intercept(Invocation invocation) throws Throwable {
        // implement pre processing if need
        Object returnObject = invocation.proceed();
        // implement post processing if need
        return returnObject;
      }
      public void setProperties(Properties properties) {
        this.properties = properties;
      }
    }
    
    <!-- mybatis-config.xml -->
    <plugins>
      <plugin interceptor="org.mybatis.example.ExamplePlugin">
        <property name="someProperty" value="100"/>
      </plugin>
    </plugins>
    

    上面的插件将会拦截在 Executor 实例中所有的 “update” 方法调用, 这里的 Executor 是负责执行底层映射语句的内部对象。

  • 相关阅读:
    .java中如何实现序列化,有什么意义
    缓存穿透
    缓存击穿
    缓存雪崩
    redis缓存预热
    Docket 的常用命令
    数据库优化方法
    servlet和jsp的区别:
    6原则1法则
    学习IntelliJ IDEA(二)模块
  • 原文地址:https://www.cnblogs.com/isawu/p/14737269.html
Copyright © 2011-2022 走看看