Mybatis源码阅读执行流程

1.准备工作

1.1.mybatis.xml

里面做了数据源及mapper的一些配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<properties>
		<property name="name" value="张三" />
	</properties>
	<settings>
		<setting name="logImpl" value="STDOUT_LOGGING" />
	</settings>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url"
					value="jdbc:mysql://localhost:3306/aaa?serverTimezone=UTC" />
				<property name="username" value="root" />
				<property name="password" value="123456" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper class="com.test.mybatis.ProjectMapper"></mapper>
	</mappers>
</configuration>

1.2.project.mapper

<mapper namespace="com.test.mybatis.ProjectMapper">
	<select id="find" parameterType="int" resultType="string">
		select name from user where id = #{projectid} 
	</select>
</mapper>

1.3.mapper.class

package com.test.mybatis;
import org.apache.ibatis.annotations.Param;

public interface ProjectMapper {
	String find(@Param("projectid") int id);	
}

1.4.一个测试类

public class Test {
	public static void main(String[] args) throws IOException {
		
		String resource = "mybatis.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		SqlSession session = sqlSessionFactory.openSession();
		try {
			
		  Object selectOne = session.selectOne("com.test.mybatis.ProjectMapper.find", 1);
		  System.out.println(selectOne);
		} finally {
		  session.close();
		}
	}
}

2.DEBUG模式运行上述代码

2.1通过xml获取SqlSessionFactory,这个是全局唯一的

xml > inputStream //读取xml到inputStream
SqlSessionFactoryBuilder.build //创建SqlSessionFactory,Builder
    inputStream > XMLConfigBuilder //将inputstream 包装进XMLConfigBuilder
        Configuration = XMLConfigBuilder.parse  //要解析成Configuration
            parseConfiguration //加载配置文件
                propertiesElement(root.evalNode("properties")); // 解析<properties>
                    <properties>解析进configuration.variables // 放到Configuration里
                Properties settings = settingsAsProperties(root.evalNode("settings"));// 解析<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);
                typeHandlerElement(root.evalNode("typeHandlers"));
                databaseIdProviderElement(root.evalNode("databaseIdProvider"));


                environmentsElement(root.evalNode("environments"));// 解析<environments>
                    解析environments标签 // 获取TransactionFactory和datasource
                    configuration.setEnvironment(datasource,TransactionFactory)// 放到Configuration里
                mapperElement(root.evalNode("mappers")); // 解析mappers
                    configuration.addMapper(MapperClass.class)
                        if (class is interface){ //如果是个接口
                            knownMappers.put(type, new MapperProxyFactory<>(type));
                            MapperAnnotationBuilder.parse();
                                loadXmlResource();//解析xml //解析对应的mapper.xml
                                    XMLMapperBuilder.parse()
                                        cacheRefElement(context.evalNode("cache-ref")); //解析缓存标签
                                        cacheElement(context.evalNode("cache"));
                                        parameterMapElement(context.evalNodes("/mapper/parameterMap"));
                                        resultMapElements(context.evalNodes("/mapper/resultMap"));
                                        sqlElement(context.evalNodes("/mapper/sql"));
                                        buildStatementFromContext(context.evalNodes("select|insert|update|delete"));//解析select|insert|update|delete标签
                                            XMLStatementBuilder.parseStatementNode();//存储到最终的对象
                                configuration.addLoadedResource(resource);
                                assistant.setCurrentNamespace(type.getName());
                                parseCache();
                                parseCacheRef();
                                Method[] methods = type.getMethods();
                                for (Method method : methods) { //遍历接口的每一个方法,对应出每一个MappedStatement,放到Configuration里
                                    parseStatement(method);
                                        根据注解生成SqlSource
                                            sql = PropertyParser.parse(script,configuration.getVariables())
                                        MappedStatement statement = MappedStatement.Builder.build();//最终的对象
                                        configuration.addMappedStatement(statement);    

                                }
                        }

2.2通过SqlSessionFactory获取SqlSession,主要是拿到DataSource和事务

SqlSession session = sqlSessionFactory.openSession();
    Environment environment = configuration.getEnvironment();
    TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
    tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    Executor executor = configuration.newExecutor(tx, execType);
    return new DefaultSqlSession(configuration, executor, autoCommit);

2.3执行selectOne

SqlSession.selectOne
    DefaultSqlSession.selectOne
         List<T> list = this.selectList(statement, parameter);//查询list,然后获取list.get(0)就是selectOne.
            CachingExecutor.query
                 CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
                    if (cache){ //如果有缓存,使用缓存
                        use cache
                    }else{
                        //如果没有缓存
                        SimpleExecutor.query
                            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
                                StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);//包装出了StatementHandler
                                statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);//interceptor执行
                            Statement stmt = prepareStatement(handler, ms.getStatementLog());
                                Connection connection = getConnection(statementLog);//此时会连接数据库生成链接
                                    Connection connection = transaction.getConnection();
                                    if (statementLog.isDebugEnabled()) {
                                        return ConnectionLogger.newInstance(connection, statementLog, queryStack);
                                    } else {
                                        return connection;
                                    }
                                stmt = StatementHandler.prepare(connection, transaction.getTimeout());
                                    PreparedStatementHandler.prepare
                                        statement = instantiateStatement(connection);
                                            statement = connection.prepareStatement(sql)
                                                一顿反射
                                                    PreparedStatement stmt = (PreparedStatement) method(prepareStatement).invoke(com.mysql.cj.jdbc.ConnectionImpl, params);//jdbc
                                                    PreparedStatementLogger stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);//动态代理包装
                                handler.parameterize(stmt); //sql参数设置
                                    PreparedStatementHandler.parameterize(statement);
                                        调用PreparedStatementLogger的设置参数(动态代理)
                            return handler.query(stmt, resultHandler);
                                PreparedStatementHandler.query(PreparedStatementLogger, resultHandler)
                                    PreparedStatement ps = (PreparedStatement) statement;
                                    ps.execute();//调用PreparedStatementLogger的execute(动态代理)
                                    return resultSetHandler.handleResultSets(ps);//处理结果集        
                    }

2.4 附上PreparedStatementLogger包装类的源码


package org.apache.ibatis.logging.jdbc;

public final class PreparedStatementLogger extends BaseJdbcLogger implements InvocationHandler {


  // 如果是mysql的话,这个真实对象是com.mysql.cj.jdbc.ClientPreparedStatement,属于mysql-connect.jar里的操作数据库的对象了.
  private final PreparedStatement statement;

  private PreparedStatementLogger(PreparedStatement stmt, Log statementLog, int queryStack) {
    super(statementLog, queryStack);
    this.statement = stmt;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
    try {
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, params);
      }
      //EXECUTE_METHODS=[addBatch, execute, executeUpdate, executeQuery] 
      //EXECUTE_METHODS数组有上述四种方法,这个数组里面都是操作数据库的
      if (EXECUTE_METHODS.contains(method.getName())) {
        
        /**
         查看当前日志系统是否是debug,如果是debug就打印.如果使用的日志是StdOutImpl就默认是debug
        */
        if (isDebugEnabled()) {
          debug("Parameters: " + getParameterValueString(), true);
        }
        clearColumnInfo();
        if ("executeQuery".equals(method.getName())) {
          ResultSet rs = (ResultSet) method.invoke(statement, params);
          return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
        } else {
          return method.invoke(statement, params);//这个执行的最多
        }
        
      } else if (SET_METHODS.contains(method.getName())) {
        //SET_METHODS = [setByte, setNull, setShort, setObject, setDouble, setTimestamp, setTime, setBytes,setInt, setURL, setArray, setLong, setString...]
        //SET_METHODS 有上述的关于注入参数的一些方法.

        if ("setNull".equals(method.getName())) {
          setColumn(params[0], null);
        } else {
          setColumn(params[0], params[1]);
        }
        return method.invoke(statement, params);
      } else if ("getResultSet".equals(method.getName())) {
        ResultSet rs = (ResultSet) method.invoke(statement, params);
        return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
      } else if ("getUpdateCount".equals(method.getName())) {
        int updateCount = (Integer) method.invoke(statement, params);
        if (updateCount != -1) {
          debug("   Updates: " + updateCount, false);
        }
        return updateCount;
      } else {
        return method.invoke(statement, params);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
  }

  public static PreparedStatement newInstance(PreparedStatement stmt, Log statementLog, int queryStack) {
    InvocationHandler handler = new PreparedStatementLogger(stmt, statementLog, queryStack);
    ClassLoader cl = PreparedStatement.class.getClassLoader();
    return (PreparedStatement) Proxy.newProxyInstance(cl, new Class[]{PreparedStatement.class, CallableStatement.class}, handler);
  }


  public PreparedStatement getPreparedStatement() {
    return statement;
  }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值