Mybatis的执行流程

 


一、mybatis代码

@Test
void test1() throws Exception {
    InputStream in = Resources.getResourceAsStream("1");
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
   // 二、创建SqlSessionFactory SqlSessionFactory factory
= builder.build(in);
// 三、创建SqlSession SqlSession session
= factory.openSession();
// 四、获取Mapper UserMapper mapper
= session.getMapper(UserMapper.class);
// 五、Mapper查询 User u
= mapper.selectByPrimaryKey(1L); session.close(); System.out.println(u); }

二、创建SqlSessionFactory

  • 1. 首先mybatis中xml解析是通过SqlSessionFactoryBuilder.build()方法。
  • 2. 初始化mybatis(解析xml文件构建成Configuration对象)并初始化SqlSessionFactory对象
  • 2.1 Configuration对象:全局的配置对象,封装了所有的配置。
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    SqlSessionFactory var5;
    try {
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
     // 1. 创建configuration对象 2. 再进行build var5
= this.build(parser.parse()); } catch (Exception var14) { throw ExceptionFactory.wrapException("Error building SqlSession.", var14); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException var13) { } } return var5; }
// Configuration对象:全局的配置对象,封装了所有的配置。
public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }

1. 创建configuration对象

public Configuration parse() {
// 是否解析过
if (this.parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } else { this.parsed = true;
// 解析配置
this.parseConfiguration(this.parser.evalNode("/configuration")); return this.configuration; } }

1.1 解析配置

private void parseConfiguration(XNode root) {
    try {
//读取全局配置文件或者主配置文件中信息
this.propertiesElement(root.evalNode("properties")); Properties settings = this.settingsAsProperties(root.evalNode("settings")); this.loadCustomVfs(settings); this.loadCustomLogImpl(settings); this.typeAliasesElement(root.evalNode("typeAliases")); this.pluginElement(root.evalNode("plugins")); this.objectFactoryElement(root.evalNode("objectFactory")); this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); this.reflectorFactoryElement(root.evalNode("reflectorFactory")); this.settingsElement(settings); this.environmentsElement(root.evalNode("environments")); this.databaseIdProviderElement(root.evalNode("databaseIdProvider")); this.typeHandlerElement(root.evalNode("typeHandlers")); this.mapperElement(root.evalNode("mappers")); } catch (Exception var3) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3); } }

1.1.1 读取mappers

private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
        Iterator var2 = parent.getChildren().iterator();
        while(true) {
            while(var2.hasNext()) {
                XNode child = (XNode)var2.next();
                String resource;
                if ("package".equals(child.getName())) {
                    resource = child.getStringAttribute("name");
                    this.configuration.addMappers(resource);
                } else {
                    resource = child.getStringAttribute("resource");
                    String url = child.getStringAttribute("url");
                    String mapperClass = child.getStringAttribute("class");
                    InputStream inputStream;
                    Throwable var8;
                    XMLMapperBuilder mapperParser;
                    if (resource != null && url == null && mapperClass == null) {
                        ErrorContext.instance().resource(resource);
                        inputStream = Resources.getResourceAsStream(resource);
                        var8 = null;
                        try {
                            mapperParser = new XMLMapperBuilder(inputStream, this.configuration, resource, this.configuration.getSqlFragments());
                            mapperParser.parse();
                        } catch (Throwable var32) {
                            var8 = var32;
                            throw var32;
                        } finally {
                            if (inputStream != null) {
                                if (var8 != null) {
                                    try {
                                        inputStream.close();
                                    } catch (Throwable var29) {
                                        var8.addSuppressed(var29);
                                    }
                                } else {
                                    inputStream.close();
                                }
                            }
                        }
                    } else if (resource == null && url != null && mapperClass == null) {
                        ErrorContext.instance().resource(url);
                        inputStream = Resources.getUrlAsStream(url);
                        var8 = null;
                        try {
                            mapperParser = new XMLMapperBuilder(inputStream, this.configuration, url, this.configuration.getSqlFragments());
                            mapperParser.parse();
                        } catch (Throwable var31) {
                            var8 = var31;
                            throw var31;
                        } finally {
                            if (inputStream != null) {
                                if (var8 != null) {
                                    try {
                                        inputStream.close();
                                    } catch (Throwable var30) {
                                        var8.addSuppressed(var30);
                                    }
                                } else {
                                    inputStream.close();
                                }
                            }
                        }
                    } else {
                        if (resource != null || url != null || mapperClass == null) {
                            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
                        }
                        Class<?> mapperInterface = Resources.classForName(mapperClass);
                        this.configuration.addMapper(mapperInterface);
                    }
                }
            }
            return;
        }
    }
}

三、创建SqlSession

  • 3. 通过SqlSesssionFactory.openSession()方法打开一个SqlSession对象
  • 3.1 每个SqlSession都会创建一个事务。
  • 3.2 通过全局configuration配置类创建Execuror对象:执行器,MyBatis的调度中心,负责SQL生成和查询缓存维护,在创建SqlSession对象之前创建, 在创建OK之后,会执行InterceptorChain拦截器链pluginAll方法
  •           CachingExecuror(SimpleExecuror):带有缓存的执行器
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    DefaultSqlSession var8;
    try {
        Environment environment = this.configuration.getEnvironment();
        TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
// 创建事务 tx
= transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 创建执行器 Executor executor
= this.configuration.newExecutor(tx, execType);
// 创建SqlSession var8
= new DefaultSqlSession(this.configuration, executor, autoCommit); } catch (Exception var12) { this.closeTransaction(tx); throw ExceptionFactory.wrapException("Error opening session. Cause: " + var12, var12); } finally { ErrorContext.instance().reset(); } return var8; }

3.1 创建执行器

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? this.defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Object executor;
    if (ExecutorType.BATCH == executorType) {
        executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
        executor = new ReuseExecutor(this, transaction);
    } else {
        executor = new SimpleExecutor(this, transaction);
    }
    if (this.cacheEnabled) {
// 将executor 包装为CachingExecutor(带有缓存的Executor) executor
= new CachingExecutor((Executor)executor); } // 为每个拦截器链安装Executor Executor executor = (Executor)this.interceptorChain.pluginAll(executor); return executor; }

3.2 为每个拦截器链安装Executor

public Object pluginAll(Object target) {
    Interceptor interceptor;
    for(Iterator var2 = this.interceptors.iterator(); var2.hasNext(); target = interceptor.plugin(target)) {
        interceptor = (Interceptor)var2.next();
    }
    return target;
}

四、获取Mapper

  • 4. 通过SqlSession.getMapper()根据传入的Mapper对象类型动态代理并返回一个JDK动态代理后的Mapper对象
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
// 获取Mapper代理的工厂 MapperProxyFactory
<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } else { try {
// 通过工厂获取代理类
return mapperProxyFactory.newInstance(sqlSession); } catch (Exception var5) { throw new BindingException("Error getting mapper instance. Cause: " + var5, var5); } } }

4.1 通过工厂获取代理类

public T newInstance(SqlSession sqlSession) {
// 获取Mapper代理对象 MapperProxy
<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
// 通过JDK动态代理创建一个Mapper代理对象
return this.newInstance(mapperProxy); }

4.1.1 通过JDK动态代理创建一个Mapper代理对象

protected T newInstance(MapperProxy<T> mapperProxy) {
    return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}

5. Mapper查询

  • 由SqlSession.select(),MapperProxy对象的invoke()方法执行后再执行execure方法,再根据情况选择执行select
  • 5. Executor执行Query,在前面经过参数名封装和缓存查询之后(缓存为空),会调用方法去数据库当中查
  • SimpleExecurot执行doQuery()方法,初始化prepareStatement并且给#{}参数赋值
  • StatementHandler执行query()方法,执行sql语句
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
        return Object.class.equals(method.getDeclaringClass()) ? method.invoke(this, args) : this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession);
    } catch (Throwable var5) {
        throw ExceptionUtil.unwrapThrowable(var5);
    }
}

 

 

 

ResuletHandler.handleResultSets()方法封装结果集

 

posted @ 2022-06-08 22:25  yifanSJ  阅读(346)  评论(0编辑  收藏  举报