比如我们需要现在需要一个方法 是查询表中的全部信息 我们会这样写
@Override public List<User> selectAll() { SqlSession sqlSession = factory.openSession(); List<User> userList = sqlSession.selectList("com.tubai.dao.UserDao.selectAll"); sqlSession.close(); return userList; }主要是通过sqlSession的selectList来实现功能
那么Mybatis是如何替我们完成这一项工作的呢?
我们通过debug模式启动 当执行到这一句的时候步入
userDao = sqlSession.getMapper(UserDao.class);到
public <T> T getMapper(Class<T> type) { return this.configuration.getMapper(type, this); }next->
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return this.mapperRegistry.getMapper(type, sqlSession); }->
public <T> T getMapper(Class<T> type, SqlSession sqlSession) { MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } else { try { return mapperProxyFactory.newInstance(sqlSession); } catch (Exception var5) { throw new BindingException("Error getting mapper instance. Cause: " + var5, var5); } } }我们发现是执行了
return mapperProxyFactory.newInstance(sqlSession);继续步入->
public T newInstance(SqlSession sqlSession) { MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache); return this.newInstance(mapperProxy); }->
protected T newInstance(MapperProxy<T> mapperProxy) { return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy); }到这里我们发现是调用了动态代理的newProxyInstance方法 那么我们直接看第三个参数(是如何代理的)
打开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); } if (this.isDefaultMethod(method)) { return this.invokeDefaultMethod(proxy, method, args); } } catch (Throwable var5) { throw ExceptionUtil.unwrapThrowable(var5); } MapperMethod mapperMethod = this.cachedMapperMethod(method); return mapperMethod.execute(this.sqlSession, args); }发现它最后调用了
mapperMethod.execute(this.sqlSession, args);打开这个方法的源代码继续
public Object execute(SqlSession sqlSession, Object[] args) { Object param; Object result; switch(this.command.getType()) { case INSERT: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.insert(this.command.getName(), param)); break; case UPDATE: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.update(this.command.getName(), param)); break; case DELETE: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.delete(this.command.getName(), param)); break; case SELECT: if (this.method.returnsVoid() && this.method.hasResultHandler()) { this.executeWithResultHandler(sqlSession, args); result = null; } else if (this.method.returnsMany()) { result = this.executeForMany(sqlSession, args); } else if (this.method.returnsMap()) { result = this.executeForMap(sqlSession, args); } else if (this.method.returnsCursor()) { result = this.executeForCursor(sqlSession, args); } else { param = this.method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(this.command.getName(), param); } break; case FLUSH: result = sqlSession.flushStatements(); break; default: throw new BindingException("Unknown execution method for: " + this.command.getName()); } if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) { throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ")."); } else { return result; } }在Case:SELECT下 我们找到
result = this.executeForMany(sqlSession, args);我们点开
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) { Object param = this.method.convertArgsToSqlCommandParam(args); List result; if (this.method.hasRowBounds()) { RowBounds rowBounds = this.method.extractRowBounds(args); result = sqlSession.selectList(this.command.getName(), param, rowBounds); } else { result = sqlSession.selectList(this.command.getName(), param); } if (!this.method.getReturnType().isAssignableFrom(result.getClass())) { return this.method.getReturnType().isArray() ? this.convertToArray(result) : this.convertToDeclaredCollection(sqlSession.getConfiguration(), result); } else { return result; } }~最终我们终于发现了
sqlSession.selectList