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()方法封装结果集