• 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;
            }
        }
  • 相关阅读:
    Linux_9/ RAID & LVM
    Linux_8/ fdisk, xfs_quota, edquota
    Linux_7/(chattr, lsattr), (setfacl, getfacl),su
    Linux_6/ Vim, Shell(下),(at, crond), (SUID, SGID, SBIT)
    Linux_5/ Vim, Shell(上)
    Linux_4/ |, (>, 2>, &>, >>, 2>>)
    Map集合的遍历
    List集合三种遍历方法
    MySQL安装
    排序法
  • 原文地址:https://www.cnblogs.com/LQBlog/p/10702850.html
Copyright © 2020-2023  润新知