Mybatis源码分析-执行模块
来源:互联网 发布:金属徽章定制价格淘宝 编辑:程序博客网 时间:2024/05/21 10:06
执行模块打算分几篇记录,先大概了解下整体流程,再详细讲些个人感觉重要的点。
接着上篇例子讲
String resource = "configs/mybatis-config.xml"; Reader reader = Resources.getResourceAsReader(resource); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(reader); SqlSession session = sqlSessionFactory.openSession(); try { AppMapper mapper = session.getMapper(AppMapper.class); List<App> blog = mapper.selectByFilter(null); System.out.println(JsonUtil.objectToJson(blog)); } finally { session.close(); }
上篇已经粗略介绍过配置初始化的代码,这篇来看看 代码中try块中的代码!
1 AppMapper mapper = session.getMapper(AppMapper.class); 获取代理mapper类
从上篇应该知道,此时的session的真正执行者是DefaultSqlSession,来看看其getMapper方法
@Override 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); }
实现了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); } catch (Exception e) { throw new BindingException("Error getting mapper instance. Cause: " + e, e); } }
实现了 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并且返回
2 List blog = mapper.selectByFilter(null);
获取到mapper代理后,执行了selectByFilter方法,既然是代理类,执行的方法就应该是MapperProxy类中的invoke方法,我们来看看
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } else if (isDefaultMethod(method)) { return invokeDefaultMethod(proxy, method, args); } } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } final MapperMethod mapperMethod = cachedMapperMethod(method); return mapperMethod.execute(sqlSession, args); }
Object.class.equals(method.getDeclaringClass()) 这个判断基本上可以没用了,我们一般都是用接口
往下走,出现MapperMethod,来看看他的execute方法
public Object execute(SqlSession sqlSession, Object[] args) { Object result; switch (command.getType()) { case INSERT: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.insert(command.getName(), param)); break; } case UPDATE: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.update(command.getName(), param)); break; } case DELETE: { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.delete(command.getName(), param)); break; } case SELECT: 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 if (method.returnsCursor()) { result = executeForCursor(sqlSession, args); } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); } break; case FLUSH: result = sqlSession.flushStatements(); break; default: 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; }
我们的例子中走的是 executeForMany方法,返回列表
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) { List<E> result; Object param = method.convertArgsToSqlCommandParam(args); if (method.hasRowBounds()) { RowBounds rowBounds = method.extractRowBounds(args); result = sqlSession.<E>selectList(command.getName(), param, rowBounds); } else { result = sqlSession.<E>selectList(command.getName(), param); } // issue #510 Collections & arrays support if (!method.getReturnType().isAssignableFrom(result.getClass())) { if (method.getReturnType().isArray()) { return convertToArray(result); } else { return convertToDeclaredCollection(sqlSession.getConfiguration(), result); } } return result; }
好吧,绕了大圈 ,又回到sqlSession.selectList方法
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try { MappedStatement ms = configuration.getMappedStatement(statement); return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
终于到了执行器这里了,此时的executor是CachingExecutor代理,先从缓存过一遍,如果不存在,则从库中获取
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { Set<Method> methods = signatureMap.get(method.getDeclaringClass()); if (methods != null && methods.contains(method)) { return interceptor.intercept(new Invocation(target, method, args)); } return method.invoke(target, args); } catch (Exception e) { throw ExceptionUtil.unwrapThrowable(e); } }
从代理中走了一圈,看看是否有插件的存在,有插件则走插件,无插件走原方法,咱这里没插件!
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameterObject); CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql); return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); }
这里先不讲缓存了,继续经过一级缓存的判断,没有的情况下,继续执行SimpleExecutor执行器
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
二级缓存的判断,也没有,则
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
从数据库中获取数据
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(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); stmt = prepareStatement(handler, ms.getStatementLog()); return handler.<E>query(stmt, resultHandler); } finally { closeStatement(stmt); } }
终于出现Statement关键类了
StatementHandler 四大类之一
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); stmt = handler.prepare(connection, transaction.getTimeout()); handler.parameterize(stmt); return stmt; }
分析下 这块
Connection connection = getConnection(statementLog);
这个方法里面涉及到数据连接池(当然你也可以配置不用连接池,但为什么不用呢?),也就是说 优先从连接池中获取链接,如果过期,则删除过期链接重新生成一个链接。连接池具体怎么样不是本篇内容。然后返回的链接时一个ConnectionLogger的代理,来看看invoke内容
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { try { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, params); } if ("prepareStatement".equals(method.getName())) { if (isDebugEnabled()) { debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true); } PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params); stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack); return stmt; } else if ("prepareCall".equals(method.getName())) { if (isDebugEnabled()) { debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true); } PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params); stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack); return stmt; } else if ("createStatement".equals(method.getName())) { Statement stmt = (Statement) method.invoke(connection, params); stmt = StatementLogger.newInstance(stmt, statementLog, queryStack); return stmt; } else { return method.invoke(connection, params); } } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } }
好吗 在使用connection生成Statment的时候,就执行了该invoke内容了。
stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
又使用代理,返回PreparedStatementLogger代理
到此 Statement 已经创建好了
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { try { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, params); } if (EXECUTE_METHODS.contains(method.getName())) { 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())) { 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); } }
接下来Statement每一个操作都会进入PreparedStatementLogger的invoke方法中 ,可见 它只处理executeQuery,setNull,getResultSet,getUpdateCount的方法调用,其他还是调用原方法
接下来 是ParameterHandler,四大类之一,主要是处理参数的操作
@Override public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { PreparedStatement ps = (PreparedStatement) statement; ps.execute(); return resultSetHandler.<E> handleResultSets(ps); }
走到PreparedStatementHandler中的query方法,执行sql语句了,接下来就是对结果集的处理了,ResultSetHandler四大类之一,主要处理结果数据转换!
public List<Object> handleResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity("handling results").object(mappedStatement.getId()); final List<Object> multipleResults = new ArrayList<Object>(); int resultSetCount = 0; //获得执行的字段、字段类型等信息 ResultSetWrapper rsw = getFirstResultSet(stmt);//获得结果配置信息 List<ResultMap> resultMaps = mappedStatement.getResultMaps(); int resultMapCount = resultMaps.size(); validateResultMapsCount(rsw, resultMapCount); while (rsw != null && resultMapCount > resultSetCount) { ResultMap resultMap = resultMaps.get(resultSetCount); //对结果数据进行处理,生成实体类,循环行数据,给实体类赋值,方法中还需要考虑到类型转换器 handleResultSet(rsw, resultMap, multipleResults, null); rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } String[] resultSets = mappedStatement.getResultSets(); if (resultSets != null) { while (rsw != null && resultSetCount < resultSets.length) { ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = configuration.getResultMap(nestedResultMapId); handleResultSet(rsw, resultMap, null, parentMapping); } rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } } return collapseSingleResultList(multipleResults); }
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException { try { if (parentMapping != null) { handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping); } else { if (resultHandler == null) { DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory); //赋值 handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null); multipleResults.add(defaultResultHandler.getResultList()); } else { handleRowValues(rsw, resultMap, resultHandler, rowBounds, null); } } } finally { // issue #228 (close resultsets) closeResultSet(rsw.getResultSet()); } }
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException { DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>(); skipRows(rsw.getResultSet(), rowBounds); while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) { ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null); Object rowValue = getRowValue(rsw, discriminatedResultMap); storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet()); } }
//获取数据赋值 private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix); boolean foundValues = false; final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); //循环执行获取行数据 for (ResultMapping propertyMapping : propertyMappings) { //字段 String column = prependPrefix(propertyMapping.getColumn(), columnPrefix); if (propertyMapping.getNestedResultMapId() != null) { // the user added a column attribute to a nested result map, ignore it column = null; } if (propertyMapping.isCompositeResult() || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) || propertyMapping.getResultSet() != null) { //真实值 Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix); // issue #541 make property optional final String property = propertyMapping.getProperty(); if (property == null) { continue; } else if (value == DEFERED) { foundValues = true; continue; } if (value != null) { foundValues = true; } if (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive())) { // gcode issue #377, call setter on nulls (value is not 'found') //通过该方法进行赋值,通过set方法将值set进去 metaObject.setValue(property, value); } } } return foundValues; }
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException { final ResultLoaderMap lazyLoader = new ResultLoaderMap(); //获得实体类 Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null); if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { final MetaObject metaObject = configuration.newMetaObject(rowValue); boolean foundValues = this.useConstructorMappings; if (shouldApplyAutomaticMappings(resultMap, false)) { foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues; } //实体类赋值 foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues; foundValues = lazyLoader.size() > 0 || foundValues; rowValue = (foundValues || configuration.isReturnInstanceForEmptyRow()) ? rowValue : null; } return rowValue; }
private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { this.useConstructorMappings = false; // reset previous mapping result final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>(); final List<Object> constructorArgs = new ArrayList<Object>(); //生成实体类,这里用到ObjectFactory,即配置中介绍的可以实现实体类初始化 Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix); if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); //循环配置结果集 for (ResultMapping propertyMapping : propertyMappings) { // 判断是否延迟加载 if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) { resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs); break; } } } this.useConstructorMappings = (resultObject != null && !constructorArgTypes.isEmpty()); // set current mapping result return resultObject; }
好了 获得结果就返回,最后关闭连接,不过这里用到连接池,不会真正的关闭。
这两篇mybatis有代码,而且代码占多,并且没有注释,还是想着自己看懂就行了毕竟是粗略的过一下,这种想法不是很好,接下来几篇尽量能注释好吧!!
接下来将逐步分析以下几个模块,一个个来吧!!
1 数据源
2 缓存
3 事务
4 插件
- Mybatis源码分析-执行模块
- Mybatis源码分析-配置模块
- Mybatis源码分析之执行完整分析
- Mybatis 源码 sql执行流程分析
- Pig源码分析: 逻辑执行计划模块
- MyBatis源码分析-SQL语句执行的完整流程
- MyBatis源码分析-SQL语句执行的完整流程
- MyBatis源码学习笔记(十)SQL执行流程分析
- mybatis源码分析,sql语句执行的完整流程
- suricata 3.1 源码分析24 (数据包解码模块执行)
- 【Mybatis】mybatis插件源码分析
- Mybatis 源码解析 -事务模块
- Mybatis 源码解析 -插件模块
- MyBatis 3源码分析
- MyBatis源码分析
- mybatis源码分析
- Mybatis原理源码分析
- Mybatis源码 select分析
- 远程连接工具
- CSS标签选择器
- javascrip的一些基本操作
- leetcode -- 442. Find All Duplicates in an Array 【数组随机性 + 数据特点 + 整数符号位使用】
- POJ 1024--Tester Program
- Mybatis源码分析-执行模块
- 《算法》笔记-3.2二叉查找树
- 【机器学习杂货铺】——线性模型和非线性模型(暂缺)
- Android 7.1 icu4c(icudt56l.dat)编译
- 数据库多个触发器的连续执行
- 正则表达式详解
- 剑指offer——二进制中1的个数
- MySQL基础(6)——插入数据、更新和删除数据
- Barra 结构化风险模型实现(1)——沪深300指数的风格因子暴露度分析