获取SqlSession
mapper解析完毕后,整个configuration就算解析完成,根据sqlSessionFactory获取session,然后获取mapper执行sql
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
openSession()方法调用重载方法
//DefaultSqlSessionFactory
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
// JdbcTransactionFactory
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
// JdbcTransaction
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// CachingExecutor、
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} 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();
}
}
返回创建DefaultSqlSession
获取Mapper
BlogDao blogDao = sqlSession.getMapper(BlogDao.class);
从已解析的结果集合中取出对应的MapperProxyFactory,创建相应的代理
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来创建MapperProxy代理类,代码如下
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
MapperProxy实现了InvocationHandler接口,也就是说获取的Mapper对象方法调用最后会调用MapperProxy.invoke()
执行SQL
调用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类的方法或者default方法直接执行,其它方法 执行mapperMethod.execute(),execute方法根据类型执行相应的语句
- INSERT -> sqlSession.insert
- UPDATE -> sqlSession.update
- DELETE-> sqlSession.delete
- SELECT-> sqlSession.select*
- FLUSH-> sqlSession.flushStatements
select 方法 有多种,需要进行结果集映射,以executeForMany(sqlSession, args)为例来看,方法会调用sqlSession.<E>selectList()
// DefaultSqlSession.selectList
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
}
// CachingExecutor.query
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);
}
boundSql中包含之中要执行的sql,getBoundSql方法会通过SqlSource来获取 ,这里的sqlSource为之前解析的,存在两种:DynamicSqlSource,RawSqlSource。
- RawSqlSource相比DynamicSqlSource就简单多了,在创建RawSqlSource时直接就将sql解析了,直接获取即可。
- 动态sql会在执行时解析并转化为静态sql
调用query方法,这里调用的虽然是CachingExecutor类,但最后会委派给SimpleExecutor调用,调用会访问cache,并把结果放在cache中
@Override
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);
}
}
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
String sql = boundSql.getSql();
statement.execute(sql);
return resultSetHandler.<E>handleResultSets(statement);
}
结果映射
在处理结果集行值时分为两部分,处理简单resultMap对应的行值和处理嵌套resultMap对应的行值,是否嵌套映射在解析mapper resultMap的时候已经解释过了,这里不再重复。处理简单resultMap对应的行值稍微简单些,先看简单的映射
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
//处理分页,跳过指定的行,如果rs类型不是TYPE_FORWARD_ONLY,直接absolute,否则的话循环rs.next
skipRows(rsw.getResultSet(), rowBounds);
while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
//处理行值,重点分析
Object rowValue = getRowValue(rsw, discriminatedResultMap);
//保存对象,通过list保存生成的对象Object
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
}
}
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;
}
获取行值主要包含如下3个步骤:
createResultObject()方法创建结果集对象
根据resultType,通过ObjectFactory.create来创建对象,其实现原理还是通过反射来创建对象。在创建对象时如果resultMap未配置constructor,通过默认构造方法来创建对象,否则通过有参的构造方法来创建对象自动映射属性
applyAutomaticMappings(),如果ResultMap配置了autoMapping="true",或者AutoMappingBehavior为PARTIAL会自动映射在resultSet查询列中存在但是未在resultMap中配置的列。-
人工映射属性
映射在resultMap中配置的列,主要包括两步:获取属性的值和设置属性的值。//获取属性的值 Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix); //设置属性的值,通过反射来设置 metaObject.setValue(property, value);
private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { //获取嵌套查询对应的属性值,最终还是通过Executor.query来获取属性值 if (propertyMapping.getNestedQueryId() != null) { return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix); } else if (propertyMapping.getResultSet() != null) { addPendingChildRelation(rs, metaResultObject, propertyMapping); // TODO is that OK? return DEFERED; } else { final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler(); final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix); //通过typeHandler来获取属性的值,如StringTypeHandler获取属性值:rs.getString(columnName) return typeHandler.getResult(rs, column); } }
嵌套映射
嵌套resultMap主要用来处理collection,association属性
<resultMap id="detailedBlogResultMap" type="Blog">
<result property="id" column="id"/>
<result property="title" column="title"/>
<result property="content" column="content"/>
<association property="author" javaType="com.zero.mybatis.bean.Author">
<id property="id" column="author"/>
<id property="name" column="name"/>
<id property="age" column="age"/>
</association>
</resultMap>
<!--alias Blog-->
<select id="selectBlog" resultMap="detailedBlogResultMap">
select * from blog join author on blog.author = author.id where blog.id = 1;
</select>
Blog有一个author属性,代表Author的id
处理嵌套映射主要包括如下几个步骤:
- skipRows(rsw.getResultSet(), rowBounds); 同简单映射
- createRowKey,根据resultMap下的列创建rowKey,很有用。在如上liveCourseMap配置中,mybatis将会根据id列和course_name列的值来创建rowKey
- getRowValue
在handleRowValues()方法中,if条件成立进入handleRowValuesForNestedResultMap()方法
public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
if (resultMap.hasNestedResultMaps()) {
ensureNoRowBounds();
checkResultHandler();
handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else {
handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
}
}
private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
final DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
skipRows(rsw.getResultSet(), rowBounds);
Object rowValue = previousRowValue;
while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
//创建rowKey,根据rowKey判断对象创建没创建
final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);
//已经创建的对象会保存到nestedResultObjects
Object partialObject = nestedResultObjects.get(rowKey);
// issue #577 && #542
if (mappedStatement.isResultOrdered()) {
if (partialObject == null && rowValue != null) {
nestedResultObjects.clear();
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
}
rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
} else {
rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
if (partialObject == null) {
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
}
}
}
if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) {
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
previousRowValue = null;
} else if (rowValue != null) {
previousRowValue = rowValue;
}
}
getRowValue()方法
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, String columnPrefix, Object partialObject) throws SQLException {
final String resultMapId = resultMap.getId();
Object rowValue = partialObject;
if (rowValue != null) {
final MetaObject metaObject = configuration.newMetaObject(rowValue);
putAncestor(rowValue, resultMapId);
applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false);
ancestorObjects.remove(resultMapId);
} else {
final ResultLoaderMap lazyLoader = new ResultLoaderMap();
// 创建外部对象
rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
final MetaObject metaObject = configuration.newMetaObject(rowValue);
boolean foundValues = this.useConstructorMappings;
if (shouldApplyAutomaticMappings(resultMap, true)) {
//自动映射
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
}
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
putAncestor(rowValue, resultMapId);
//嵌套映射
foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues;
ancestorObjects.remove(resultMapId);
foundValues = lazyLoader.size() > 0 || foundValues;
rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
}
if (combinedKey != CacheKey.NULL_CACHE_KEY) {
nestedResultObjects.put(combinedKey, rowValue);
}
}
return rowValue;
}