mybatis源码阅读-执行一个sql的流程(九)

图解

图片来源:https://my.oschina.net/zudajun/blog/670373

Mapper接口调用原理

我们整合成Spring  直接使用Mapper就能执行对应的sql

表现形式

xml

    <select id="selectAll" resultType="com.liqiang.entity.Classes">
        select * from classes
    </select>

mapper

ClassesMapper classesMapper=sqlSessionFactory.openSession().getMapper(ClassesMapper.class);
List<Classes> classesList= classesMapper.selectAll();

原理

内部通过调用Configuration的MapperRegistry通过Proxy生成mapper接口的MapperProxy

代理对象

    public class MapperRegistry {
        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);
                }
            }
        }
    }
public class MapperProxy<T> implements InvocationHandler, Serializable {
    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 var5) {
                throw ExceptionUtil.unwrapThrowable(var5);
            }
        } else {
            //将Mehod传入封装成MapperMethod并调用execute方法
            MapperMethod mapperMethod = this.cachedMapperMethod(method);
            return mapperMethod.execute(this.sqlSession, args);
        }
    }

    private MapperMethod cachedMapperMethod(Method method) {
        MapperMethod mapperMethod = (MapperMethod)this.methodCache.get(method);
        if (mapperMethod == null) {
            mapperMethod = new MapperMethod(this.mapperInterface, method, this.sqlSession.getConfiguration());
            this.methodCache.put(method, mapperMethod);
        }
        return mapperMethod;
    }
}

MapperMethod

public class MapperMethod {
    public Object execute(SqlSession sqlSession, Object[] args) {
        Object param;
        Object result;
        //通过方法的操作类型进行路由   commandType是根据当前mapper的namespace+方法名字作为id去找对对应的MaperStatement的 commandType获得
        if (SqlCommandType.INSERT == this.command.getType()) {
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
        } else if (SqlCommandType.UPDATE == this.command.getType()) {
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
        } else if (SqlCommandType.DELETE == this.command.getType()) {
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
        } else if (SqlCommandType.SELECT == this.command.getType()) {
            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);
            }
        } else {
            if (SqlCommandType.FLUSH != this.command.getType()) {
                throw new BindingException("Unknown execution method for: " + this.command.getName());
            }

            result = sqlSession.flushStatements();
        }

        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;
        }
    }

 

posted @ 2019-04-13 20:52  意犹未尽  阅读(355)  评论(0编辑  收藏  举报