MyBatis的Sql执行过程源码解读
2015-04-03 14:19
447 查看
1.先获得SqlSessionFactory
通过SqlSessionFactoryBuilder去读取mybatis的配置文件,然后build一个DefaultSqlSessionFactory。
2.通过SqlSessionFactory去获取SqlSession对象
3.通过SqlSession获得Mapper
继续看MapperRegistry的getMapper方法
knownMappers在读取配置文件的时候,已经将mapper信息放入其中了。
继续看MapperProxyFactory的newInstance方法:
这样的话就会返回一个mapper的代理类,每次执行的时候,回交给MapperMethod类的execute方法
通过SqlSessionFactoryBuilder去读取mybatis的配置文件,然后build一个DefaultSqlSessionFactory。
/** * 一系列的构造方法最终都会调用本方法(配置文件为Reader时会调用本方法,还有一个InputStream方法与此对应) * @param reader * @param environment * @param properties * @return */ public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { //通过XMLConfigBuilder解析配置文件,解析的配置相关信息都会封装为一个Configuration对象 XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); //这儿创建DefaultSessionFactory对象 return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
2.通过SqlSessionFactory去获取SqlSession对象
public SqlSession openSession() { return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false); }
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { //通过Configuration对象去获取相关的配置信息,Environment对象包含了数据源和事务的配置 final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); //实际上就是Executor来执行sql语句,executor是对于Statement的封装 final Executor executor = configuration.newExecutor(tx, execType, autoCommit); //创建DefaultSqlSession对象 return new DefaultSqlSession(configuration, executor); } 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(); } }这样就获得了SqlSession对象
3.通过SqlSession获得Mapper
public <T> T getMapper(Class<T> type) { return configuration.<T>getMapper(type, this); }这里通过Configuration的getMapper方法来获得
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); }
protected MapperRegistry mapperRegistry = new MapperRegistry(this);
继续看MapperRegistry的getMapper方法
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type); if (mapperProxyFactory == null) throw new BindingException("Type " + type + " is not known to the MapperRegistry."); try { return mapperProxyFactory.newInstance(sqlSession); //此处使用反射,生成一个MapperProxyFactory对象 } catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); } }
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);"> </span>
knownMappers在读取配置文件的时候,已经将mapper信息放入其中了。
继续看MapperProxyFactory的newInstance方法:
protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); } public T newInstance(SqlSession sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy); }MapperProxy就是一个代理类,使用的是jdk的动态代理
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } final MapperMethod mapperMethod = cachedMapperMethod(method); return mapperMethod.execute(sqlSession, args); }这里的invoke方法可以明确看出使用的是jdk的动态代理
这样的话就会返回一个mapper的代理类,每次执行的时候,回交给MapperMethod类的execute方法
public Object execute(SqlSession sqlSession, Object[] args) { Object result; if (SqlCommandType.INSERT == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.insert(command.getName(), param)); } else if (SqlCommandType.UPDATE == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.update(command.getName(), param)); } else if (SqlCommandType.DELETE == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.delete(command.getName(), param)); } else if (SqlCommandType.SELECT == command.getType()) { if (method.returnsVoid() && method.hasResultHandler()) { executeWithResultHandler(sqlSession, args); result = null; } else if (method.returnsMany()) { result = executeForMany(sqlSession, args); } else if (method.returnsMap()) { result = executeForMap(sqlSession, args); } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); } } else { throw new BindingException("Unknown execution method for: " + command.getName()); } if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { throw new BindingException("Mapper method '" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; }可以看出,也就是判断一下CURD的类型,然后实际调用的还是SqlSession 的方法,在这里以selectList为例
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try { MappedStatement ms = configuration.getMappedStatement(statement); List<E> result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); return result; } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }继续查找Executor的query方法,在这里使用BaseExecutor的
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameter); CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql); return query(ms, parameter, rowBounds, resultHandler, key, boundSql); }继续查找到SimpleExecutor的doQuery,可以看到
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try { Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler, boundSql); stmt = prepareStatement(handler, ms.getStatementLog()); return handler.<E>query(stmt, resultHandler); } finally { closeStatement(stmt); } }
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); stmt = handler.prepare(connection); handler.parameterize(stmt); return stmt; }可以看出实际上也就好似调用的jdbc
相关文章推荐
- mybatis源码学习之执行过程分析(4)——映射文件中sql的获取和sql语句的执行
- mybatis源码学习之执行过程分析(5)——sql执行后ResultSet的处理及结果返回
- MyBatis 源码解析:通过源码深入理解 SQL 的执行过程
- Mybatis源码解析-Mapper执行SQL过程
- Mybatis源码分析之Mapper执行SQL过程(三)
- mybatis源码学习之执行过程分析(1)——SqlSessionFactory及SqlSession的创建
- mybatis_sql执行过程源码解析
- MyBatis 源码解析:通过源码深入理解 SQL 的执行过程
- 一个通用的分页存储过程实现-SqlServer(附上sql源码,一键执行即刻搭建运行环境)
- MyBatis源码分析-SQL语句执行的完整流程
- 初看Mybatis 源码 (三) SQL是怎么执行的
- myBatis接口编程,Junit测试,打印Sql执行过程
- MyBatis源码分析-SQL语句执行的完整流程
- mybatis源码学习之执行过程分析(3)——mapper接口的获取
- Mybatis中SQL语句执行过程详解
- mybatis源码学习之执行过程分析(2)——config.xml配置文件和mapper.xml映射文件解析过程
- Mybatis3源码分析(16)-Sql解析执行-结果集映射(ResultSetHandler)
- Mybatis3源码分析(14)-Sql解析执行-StatementHandler
- mysql源码分析之SQL执行过程简介
- Mybatis3源码分析(13)-Sql解析执行-BoundSql的加载-2