zoukankan      html  css  js  c++  java
  • 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;
            }
        }
  • 相关阅读:
    Codeforces 845E Fire in the City 线段树
    Codeforces 542D Superhero's Job dp (看题解)
    Codeforces 797F Mice and Holes dp
    Codeforces 408D Parcels dp (看题解)
    Codeforces 464D World of Darkraft
    Codeforces 215E Periodical Numbers 容斥原理
    Codeforces 285E Positions in Permutations dp + 容斥原理
    Codeforces 875E Delivery Club dp
    Codeforces 888F Connecting Vertices 区间dp (看题解)
    Codeforces 946F Fibonacci String Subsequences dp (看题解)
  • 原文地址:https://www.cnblogs.com/LQBlog/p/10702850.html
Copyright © 2011-2022 走看看