源码分析前简介
首先我们来看看用 Mybatis 执行 sql 的两种方法
直接操作 SqlSession 方法
public User findUserById(Integer userId) {
SqlSession sqlSession = MyBatisSqlSessionFactory.getSqlSession();
try {
// namespace + statementId
return sqlSession.selectOne("com.xuyu.mybatis.UserMapper.findUserById", userId);
} finally {
sqlSession.close();
}
}
通过 Mapper 接口
public User findUserById(Integer userId) {
SqlSession sqlSession = MyBatisSqlSessionFactory.getSqlSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
return userMapper.findUserById(userId);
} finally {
sqlSession.close();
}
}
public class UserMapper {
User findUserById(@Param("userId") String userId);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.objcoding.mybatis.UserMapper">
<select id="findUserById" resultType="com.xuyu.mybatis.User">
SELECT * FROM user WHERE user_id=#{userId}
</select>
</mapper>
源码分析流程图
1.从MapperRegistry获取查询对应绑定接口
2.动态生成代理对象
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);
}
}
3.调用MapperProxyFactory去帮我们创建代理类
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//检查看下有没有注册mapper接口
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);
}
}
创建代理类
public T newInstance(SqlSession sqlSession) {
//创建代理类
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
4.执行这条语句
UserEntity user = mapper.getUser(2);
5.跳转到MapperProxy的invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
try {
return method.invoke(this, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
//这里源码分析缓存
final MapperMethod mapperMethod = cachedMapperMethod(method);
//这里源码分析执行
return mapperMethod.execute(sqlSession, args);
}
6.执行到这条语句
final MapperMethod mapperMethod = cachedMapperMethod(method);
private MapperMethod cachedMapperMethod(Method method) {
MapperMethod mapperMethod = methodCache.get(method);
if (mapperMethod == null) {
//进入这里的构造函数
mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
methodCache.put(method, mapperMethod);
}
return mapperMethod;
}
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
//这里构建sql,源码分析
this.command = new SqlCommand(config, mapperInterface, method);
this.method = new MethodSignature(config, method);
}
public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
String statementName = mapperInterface.getName() + "." + method.getName();
MappedStatement ms = null;
if (configuration.hasStatement(statementName)) {
ms = configuration.getMappedStatement(statementName);
} else if (!mapperInterface.equals(method.getDeclaringClass())) { // issue #35
String parentStatementName = method.getDeclaringClass().getName() + "." + method.getName();
if (configuration.hasStatement(parentStatementName)) {
ms = configuration.getMappedStatement(parentStatementName);
}
}
if (ms == null) {
if(method.getAnnotation(Flush.class) != null){
name = null;
type = SqlCommandType.FLUSH;
} else {
throw new BindingException("Invalid bound statement (not found): " + statementName);
}
} else {
name = ms.getId();
type = ms.getSqlCommandType();
if (type == SqlCommandType.UNKNOWN) {
throw new BindingException("Unknown execution method for: " + name);
}
}
}
回到invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
try {
return method.invoke(this, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
//这里源码分析开始
return mapperMethod.execute(sqlSession, args);
}
7.进入到MapperMethod的execute方法就能简单找到SqlSession的删除、更新、查询、选择方法
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);
//底层执行SQL语句,封装User结果集
result = sqlSession.selectOne(command.getName(), param);
}
} else if (SqlCommandType.FLUSH == command.getType()) {
result = sqlSession.flushStatements();
} 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;
}
版权@须臾之余https://my.oschina.net/u/3995125
本文参考蚂蚁课堂:http://www.mayikt.com