zoukankan      html  css  js  c++  java
  • spring mybatis3,接口调用,pagerHelper

    接口调用: http://localhost:8080/testBoot/getUser/25:

    public String GetUser(@PathVariable int id){
            return userMapper.Sel(id).toString();    //userMapper = org.apache.ibatis.binding.MapperProxy。jdk动态代理。
        }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
                if (method.getDeclaringClass() != DecoratingProxy.class) { 
                    target = targetSource.getTarget();   //org.apache.ibatis.binding.MapperProxy@357ba95
                    Class<?> targetClass = target != null ? target.getClass() : null;
                    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);   //method = public abstract com.example.entity.User com.example.mapper.UserMapper.Sel(int),返回
                    if (chain.isEmpty()) { 
                    } else {
                        MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                        retVal = invocation.proceed();
                    }
            }  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try { 
        final MapperMethod mapperMethod = cachedMapperMethod(method);   //com.example.mapper.UserMapper.Sel就是调用的方法,
        return mapperMethod.execute(sqlSession, args);    //sqlSession = SQLSessionTemplate
      }
    public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        switch (command.getType()) {
          case INSERT: { 
          }
          case UPDATE: { 
          }
          case DELETE: { 
          }
          case SELECT: 
            } else {
              Object param = method.convertArgsToSqlCommandParam(args);
              result = sqlSession.selectOne(command.getName(), param);     //command.getName() = com.example.mapper.UserMapper.Sel,param = 25,sqlSession = SQLSessionTemplate
            }
            break;
          case FLUSH:
            result = sqlSession.flushStatements();
            break;   }
        return result;
      }
    SqlSessionTemplate类:
    public <T> T selectOne(String statement, Object parameter) {
        return this.sqlSessionProxy.<T> selectOne(statement, parameter);   // statement = com.example.mapper.UserMapper.Sel,parameter = 25。this.sqlSessionProxy = (SqlSession) newProxyInstance(
            SqlSessionFactory.class.getClassLoader(),
            new Class[] { SqlSession.class },
            new SqlSessionInterceptor());   动态代理,先去执行SqlSessionInterceptor的invoke方法,在invoke方法里面去执行真正的方法。
      }
    sqlSessionProxy的selectOne方法,selectOne是一个动态代理,最后调到SqlSessionInterceptor类的invoke方法:
    private class SqlSessionInterceptor implements InvocationHandler {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory,SqlSessionTemplate.this.executorType,SqlSessionTemplate.this.exceptionTranslator);  //返回DefaultSqlSession,
          try {
            Object result = method.invoke(sqlSession, args);       //动态代理真正方法的执行
            if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { 
              sqlSession.commit(true);    //提交,不是这里提交的,已经提交了。
            }
            return result;
          }  finally {
            if (sqlSession != null) {
              closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);    //关闭连接
            }
          }
        }
      }
    public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {  
        session = sessionFactory.openSession(executorType);//没有使用连接池,每次都会创建和销毁SqlSession
        registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);
        return session;
      }
    DefaultSqlSessionFactory类:
    public SqlSession openSession(ExecutorType execType) {
        return openSessionFromDataSource(execType, null, false);
      }
    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;
        try {
          final Environment environment = configuration.getEnvironment();
          final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
          tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
          final Executor executor = configuration.newExecutor(tx, execType);    //第一个过滤器
          return new DefaultSqlSession(configuration, executor, autoCommit);
        }   
      }
    public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {
        return new SpringManagedTransaction(dataSource);
      }
    public Executor newExecutor(Transaction transaction, ExecutorType executorType) { 
        Executor executor;
        if (ExecutorType.BATCH == executorType) { 
        } else {
          executor = new SimpleExecutor(this, transaction);
        }
        if (cacheEnabled) {
          executor = new CachingExecutor(executor);   //SimpleExecutor外面包装一层CachingExecutor,过滤器。
        }
        executor = (Executor) interceptorChain.pluginAll(executor);   //返回的是一个代理。
        return executor;
      }
    public Object pluginAll(Object target) {
        for (Interceptor interceptor : interceptors) {   //插件,pagerhelper插件,PageInterceptor
          target = interceptor.plugin(target);
        }
        return target;
      }
    PageInterceptor类:
    public Object plugin(Object target) {
            //TODO Spring bean 方式配置时,如果没有配置属性就不会执行下面的 setProperties 方法,就不会初始化,因此考虑在这个方法中做一次判断和初始化 
            return Plugin.wrap(target, this);    //target = CachingExecutor,this = PageInterceptor
        }
    public static Object wrap(Object target, Interceptor interceptor) {
        Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
        Class<?> type = target.getClass();    //class org.apache.ibatis.executor.CachingExecutor
        Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
        if (interfaces.length > 0) {
          return Proxy.newProxyInstance(
              type.getClassLoader(),
              interfaces,
              new Plugin(target, interceptor, signatureMap));    //target = org.apache.ibatis.executor.CachingExecutor,里面delegate=SimpleExecutor,interceptor = PageInterceptor。返回一个动态代理。
        }
        return target;
      }
     //插件,pagerhelper插件,PageInterceptor
    getBean(userMapper)之后,再去getBean(com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration);时候。get这2个bean是独立的没有影响的。
    getBean(com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration);
    exposedObject = initializeBean(beanName, exposedObject, mbd);    //beanName = com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); //beanName = com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration
    PageHelperAutoConfiguration类:
    public void addPageInterceptor() {
            PageInterceptor interceptor = new PageInterceptor(); 
            for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
                sqlSessionFactory.getConfiguration().addInterceptor(interceptor);   
            }
        }
    public void addInterceptor(Interceptor interceptor) {
        interceptorChain.addInterceptor(interceptor);    //把pagehelper加到拦截器,所以上面interceptors就有这个pagehelper了。
      }
    public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
        this.configuration = configuration;
        this.executor = executor;
        this.dirty = false;
        this.autoCommit = autoCommit;
      }

    Object result = method.invoke(sqlSession, args);

    public <T> T selectOne(String statement, Object parameter) { 
        List<T> list = this.<T>selectList(statement, parameter);  //statement = com.example.mapper.UserMapper.Sel,parameter = 25
        if (list.size() == 1) {
          return list.get(0);   //com.example.entity.User@7d592c2e
        }  
      }
    
    public <E> List<E> selectList(String statement, Object parameter) {
        return this.selectList(statement, parameter, RowBounds.DEFAULT);
      }
    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
        try {
          MappedStatement ms = configuration.getMappedStatement(statement);
          return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);    //拦截器开始执行。org.apache.ibatis.executor.CachingExecutor
        } 
      }
    Plugin类:
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    //proxy = org.apache.ibatis.executor.CachingExecutor,
        try {
          Set<Method> methods = signatureMap.get(method.getDeclaringClass());
          if (methods != null && methods.contains(method)) {
            return interceptor.intercept(new Invocation(target, method, args));    //interceptor = PageInterceptor,target = CachingExecutor,
          } 
        } 
      }
    PageInterceptor类:
    public Object intercept(Invocation invocation) throws Throwable {
            try {
                Object[] args = invocation.getArgs();
                MappedStatement ms = (MappedStatement) args[0];
                Object parameter = args[1];
                RowBounds rowBounds = (RowBounds) args[2];
                ResultHandler resultHandler = (ResultHandler) args[3];
                Executor executor = (Executor) invocation.getTarget();    //target = CachingExecutor,
                CacheKey cacheKey;
                BoundSql boundSql;
                //由于逻辑关系,只会进入一次
                if(args.length == 4){
                    //4 个参数时
                    boundSql = ms.getBoundSql(parameter);    //select * from money where id = ?
                    cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);    //executor = CachingExecutor,返回//868805043:3351384746:com.example.mapper.UserMapper.Sel:0:2147483647:select * from money where id = ?:25:SqlSessionFactoryBean
                } else {
                    //6 个参数时
                    cacheKey = (CacheKey) args[4];
                    boundSql = (BoundSql) args[5];
                }
                List resultList;
                //调用方法判断是否需要进行分页,如果不需要,直接返回结果
                if (!dialect.skip(ms, parameter, rowBounds)) {
                    //反射获取动态参数
                    String msId = ms.getId();    //com.example.mapper.UserMapper.Sel
                    Configuration configuration = ms.getConfiguration();   
                    Map<String, Object> additionalParameters = (Map<String, Object>) additionalParametersField.get(boundSql);
                    //判断是否需要进行 count 查询
                    if (dialect.beforeCount(ms, parameter, rowBounds)) {
                        String countMsId = msId + countSuffix;    //com.example.mapper.UserMapper.Sel_COUNT
                        Long count;
                        //先判断是否存在手写的 count 查询
                        MappedStatement countMs = getExistedMappedStatement(configuration, countMsId);
                        if(countMs != null){
                            count = executeManualCount(executor, countMs, parameter, boundSql, resultHandler);
                        } else {
                            countMs = msCountMap.get(countMsId);
                            //自动创建
                            if (countMs == null) { 
                            }
                            count = executeAutoCount(executor, countMs, parameter, boundSql, rowBounds, resultHandler); //返回1,只有一条数据,先查询总数,
                        }
                        //处理查询总数
                        //返回 true 时继续分页查询,false 时直接返回。查询count=0就不用查询了。
                        if (!dialect.afterCount(count, parameter, rowBounds)) {
                            //当查询总数为 0 时,直接返回空的结果。
                            return dialect.afterPage(new ArrayList(), parameter, rowBounds);
                        }
                    }
                    //判断是否需要进行分页查询
                    if (dialect.beforePage(ms, parameter, rowBounds)) {
                        //生成分页的缓存 key
                        CacheKey pageKey = cacheKey;  //868805043:3351384746:com.example.mapper.UserMapper.Sel:0:2147483647:select * from money where id = ?:25:SqlSessionFactoryBean
                        //处理参数对象
                        parameter = dialect.processParameterObject(ms, parameter, boundSql, pageKey);    //{First_PageHelper=0, Second_PageHelper=2, id=25}
                        //调用方言获取分页 sql
                        String pageSql = dialect.getPageSql(ms, boundSql, parameter, rowBounds, pageKey);   //select * from money where id = ? LIMIT ? 
                        BoundSql pageBoundSql = new BoundSql(configuration, pageSql, boundSql.getParameterMappings(), parameter);     //select * from money where id = ? LIMIT ? 
                        //设置动态参数
                        for (String key : additionalParameters.keySet()) {
                            pageBoundSql.setAdditionalParameter(key, additionalParameters.get(key));
                        }
                        //执行分页查询
                        resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, pageKey, pageBoundSql);    //先执行查询总数,在是真正的查询。 //com.example.entity.User@7d592c2e,物理分页。
                    } else {
                        //不执行分页的情况下,也不执行内存分页
                        resultList = executor.query(ms, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, boundSql);
                    }
                } else {
                    //rowBounds用参数值,不使用分页插件处理时,仍然支持默认的内存分页
                    resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
                }
                return dialect.afterPage(resultList, parameter, rowBounds);
            } finally {
                dialect.afterAll();
            }
        }
    public Object afterPage(List pageList, Object parameterObject, RowBounds rowBounds) {
            //这个方法即使不分页也会被执行,所以要判断 null
            AbstractHelperDialect delegate = autoDialect.getDelegate();
            if(delegate != null){
                return delegate.afterPage(pageList, parameterObject, rowBounds);
            }
            return pageList;
        }
    public Object afterPage(List pageList, Object parameterObject, RowBounds rowBounds) {
            Page page = getLocalPage();
            if (page == null) {
                return pageList;
            }
            page.addAll(pageList);
            if (!page.isCount()) {
                page.setTotal(-1);
            } else if ((page.getPageSizeZero() != null && page.getPageSizeZero()) && page.getPageSize() == 0) {
                page.setTotal(pageList.size());
            } else if(page.isOrderByOnly()){
                page.setTotal(pageList.size());
            }
            return page;
        }
    CachingExecutor类:
    public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
        return delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);   //delegate = SimpleExecutor
      }
    public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) { 
        CacheKey cacheKey = new CacheKey();
        cacheKey.update(ms.getId());
        cacheKey.update(rowBounds.getOffset());
        cacheKey.update(rowBounds.getLimit());
        cacheKey.update(boundSql.getSql());
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHa 
        return cacheKey; //868805043:3351384746:com.example.mapper.UserMapper.Sel:0:2147483647:select * from money where id = ?:25:SqlSessionFactoryBean
      }
    private Long executeAutoCount(Executor executor, MappedStatement countMs,
                                       Object parameter, BoundSql boundSql,
                                       RowBounds rowBounds, ResultHandler resultHandler) throws IllegalAccessException, SQLException {
            Map<String, Object> additionalParameters = (Map<String, Object>) additionalParametersField.get(boundSql);
            //创建 count 查询的缓存 key
            CacheKey countKey = executor.createCacheKey(countMs, parameter, RowBounds.DEFAULT, boundSql);    //executor = CachingExecutor,返回-888539805:2639554458:com.example.mapper.UserMapper.Sel_COUNT:0:2147483647:select * from money where id = ?:25:SqlSessionFactoryBean
            //调用方言获取 count sql
            String countSql = dialect.getCountSql(countMs, boundSql, parameter, rowBounds, countKey);    //SELECT count(0) FROM money WHERE id = ?
            //countKey.update(countSql);
            BoundSql countBoundSql = new BoundSql(countMs.getConfiguration(), countSql, boundSql.getParameterMappings(), parameter);    //SELECT count(0) FROM money WHERE id = ?
            //当使用动态 SQL 时,可能会产生临时的参数,这些参数需要手动设置到新的 BoundSql 中
            for (String key : additionalParameters.keySet()) {
                countBoundSql.setAdditionalParameter(key, additionalParameters.get(key));
            }
            //执行 count 查询
            Object countResultList = executor.query(countMs, parameter, RowBounds.DEFAULT, resultHandler, countKey, countBoundSql); //executor = CachingExecutor, //返回1,只有一条数据
            Long count = (Long) ((List) countResultList).get(0);
            return count;
        }
    CachingExecutor类:
    public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
          throws SQLException {
        Cache cache = ms.getCache();
        if (cache != null) {   //缓存没用到,mybtis的缓存不要用。缓存都是对查询语句缓存,
          flushCacheIfRequired(ms);
          if (ms.isUseCache() && resultHandler == null) {
            ensureNoOutParams(ms, boundSql);
            @SuppressWarnings("unchecked")
            List<E> list = (List<E>) tcm.getObject(cache, key);
            if (list == null) {
              list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
              tcm.putObject(cache, key, list); // issue #578 and #116
            }
            return list;
          }
        }
        return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);   //delegate = SimpleExecutor
      }
    SimpleExecutor父类BaseExecutor:
    public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());    //ms.getResource() = file [E:CodemybatisspringBoot_Mybatis-masterspringBoot_Mybatis-masterSpringboot_Mybatis	argetclassesmappingUserMapper.xml],
    ms.getId() = com.example.mapper.UserMapper.Sel_COUNT 
        if (queryStack == 0 && ms.isFlushCacheRequired()) {
          clearLocalCache();
        }
        List<E> list;
        try {
          queryStack++;
          list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;    //key = -888539805:2639554458:com.example.mapper.UserMapper.Sel_COUNT:0:2147483647:select * from money where id = ?:25:SqlSessionFactoryBean
          if (list != null) {
            handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
          } else {
            list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); //com.example.entity.User@7d592c2e
          }
        } finally {
          queryStack--;
        } 
        return list;
      }
    SimpleExecutor父类BaseExecutor:
    private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        List<E> list;
        localCache.putObject(key, EXECUTION_PLACEHOLDER);    //加入到缓存,
        try {
          list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);   //返回1,只有一条数据, //com.example.entity.User@7d592c2e
        } finally {
          localCache.removeObject(key);
        }
        localCache.putObject(key, list);//{1346928873:3351384750:com.example.mapper.UserMapper.Sel:0:2147483647:select * from money where id = ?:25:      SqlSessionFactoryBean:0:2:2=[com.example.entity.User@7d592c2e], -888539805:2639554458:com.example.mapper.UserMapper.Sel_COUNT:0:2147483647:select * from money where id = ?:25:      SqlSessionFactoryBean=[1]}  缓存。
        if (ms.getStatementType() == StatementType.CALLABLE) {
          localOutputParameterCache.putObject(key, parameter);
        }
        return list;
      }
    public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        Statement stmt = null;
        try {
          Configuration configuration = ms.getConfiguration();
          StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
          stmt = prepareStatement(handler, ms.getStatementLog());
          return handler.<E>query(stmt, resultHandler);
        } finally {
          closeStatement(stmt);
        }
      }
    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
        Statement stmt;
        Connection connection = getConnection(statementLog);
        stmt = handler.prepare(connection, transaction.getTimeout());
        handler.parameterize(stmt);    //设置sql语句里面的?对应的值。
        return stmt;
      }
    protected Connection getConnection(Log statementLog) throws SQLException {
        Connection connection = transaction.getConnection();
        if (statementLog.isDebugEnabled()) {
          return ConnectionLogger.newInstance(connection, statementLog, queryStack);    //对connection生成一个动态代理,用于日志打印。
        } else {
          return connection;
        }
      }
    public static Connection newInstance(Connection conn, Log statementLog, int queryStack) {
        InvocationHandler handler = new ConnectionLogger(conn, statementLog, queryStack);
        ClassLoader cl = Connection.class.getClassLoader();
        return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler);
      }
    RoutingStatementHandler类:
    public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
        return delegate.prepare(connection, transactionTimeout);
      }
    BaseStatementHandler类:
    public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
        ErrorContext.instance().sql(boundSql.getSql());
        Statement statement = null;
        try {
          statement = instantiateStatement(connection);
          setStatementTimeout(statement, transactionTimeout);
          setFetchSize(statement);
          return statement;
        } 
      }
    protected Statement instantiateStatement(Connection connection) throws SQLException {
        String sql = boundSql.getSql();   //insert into money (id, name, money) values (?, ?, ?)
        if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
          String[] keyColumnNames = mappedStatement.getKeyColumns(); 
        } else {
          return connection.prepareStatement(sql);   //connection是一个动态代理,会去调用ConnectionLogger的invoke方法。
        }
      }
    ConnectionLogger类:
    public Object invoke(Object proxy, Method method, Object[] params)
          throws Throwable {
        try { 
          if ("prepareStatement".equals(method.getName())) {
            if (isDebugEnabled()) {
              debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);    //打印sql语句,不需要log4J,只需要application-dev.yml配置logging:  level: com: example:  mapper : debug  就可以打印sql语句了。
            }        
            PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);   //被代理对象的调用,动态代理真正方法的执行,connection的prepareStatement方法。所以这里的动态代理增强就是用于日志打印。
            stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);     //这里又是动态代理增强,就是用于日志打印。
            return stmt; 
      }
    public static PreparedStatement newInstance(PreparedStatement stmt, Log statementLog, int queryStack) {
        InvocationHandler handler = new PreparedStatementLogger(stmt, statementLog, queryStack);   //日志打印的动态代理
        ClassLoader cl = PreparedStatement.class.getClassLoader();
        return (PreparedStatement) Proxy.newProxyInstance(cl, new Class[]{PreparedStatement.class, CallableStatement.class}, handler);
      }
    
    public void parameterize(Statement statement) throws SQLException {
        delegate.parameterize(statement);  //设置sql语句里面的?对应的值。
      }
    public void parameterize(Statement statement) throws SQLException {
        parameterHandler.setParameters((PreparedStatement) statement);
      }
    RoutingStatementHandler类:
    public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
        return delegate.<E>query(statement, resultHandler);
      }
    PreparedStatementHandler类:
    public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
        PreparedStatement ps = (PreparedStatement) statement;
        ps.execute();   //ps是一个动态代理增强,用于日志打印,就是上面的:Proxy.newProxyInstance(cl, new Class[]{PreparedStatement.class, CallableStatement.class}, handler);所以先去执行PreparedStatementLogger的invoke,然后在invoke方法里面去执行真正的方法调用,
        return resultSetHandler.<E> handleResultSets(ps);  //对结果集的封装,ps是查询的结果。
      }
    PreparedStatementLogger类:
    public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
        try {
          if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, params);
          }          
          if (EXECUTE_METHODS.contains(method.getName())) { 
            if (isDebugEnabled()) {
              debug("Parameters: " + getParameterValueString(), true);     //打印sql的查询参数,不需要log4J,只需要application-dev.yml配置logging:  level: com: example:  mapper : debug  就可以打印sql语句了。
            }
            clearColumnInfo();
            if ("executeQuery".equals(method.getName())) {
              ResultSet rs = (ResultSet) method.invoke(statement, params);
              return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
            } else {
              return method.invoke(statement, params);   //method = public abstract boolean java.sql.PreparedStatement.execute() ,动态代理真正方法的执行,
            }
          } 
    ProxyPreparedStatement类:
    public boolean execute() throws SQLException
       {
          connection.markCommitStateDirty();
          return ((PreparedStatement) delegate).execute();   //delegate = com.mysql.cj.jdbc.ClientPreparedStatement: SELECT count(0) FROM money WHERE id = 25
       }
    ClientPreparedStatement类:
    public boolean execute() throws SQLException {
            try {
                synchronized(this.checkClosed().getConnectionMutex()) {
                    JdbcConnection locallyScopedConn = this.connection;   //com.mysql.cj.conf.HostInfo@f6c2c82 :: {host: "localhost", port: 3306, user: root, password: 123456, hostProperties: {dbname=account}}    
                            rs = this.executeInternal(this.maxRows, sendPacket, this.createStreamingResultSet(), ((PreparedQuery)this.query).getParseInfo().getFirstStmtChar() == 'S', cachedMetadata, false);   //   sendPacket  =    . S E L E C T    c o u n t ( 0 ) F R O M   m o n e y   W H E R  E   i d   =   2  5  
                            if (rs != null) {
                                this.lastInsertId = rs.getUpdateID();
                                this.results = rs;
                            }
                            return rs != null && rs.hasRows();
                        }
                    }
                }
            }  
        }
    protected <M extends Message> ResultSetInternalMethods executeInternal(int maxRowsToRetrieve, M sendPacket, boolean createStreamingResultSet, boolean queryIsSelectOnly, ColumnDefinition metadata, boolean isBatch) throws SQLException {
            try {
                synchronized(this.checkClosed().getConnectionMutex()) { 
                    try {
                        JdbcConnection locallyScopedConnection = this.connection;    //com.mysql.cj.conf.HostInfo@f6c2c82 :: {host: "localhost", port: 3306, user: root, password: 123456, hostProperties: {dbname=account}}  
    
                            rs = (ResultSetInternalMethods)((NativeSession)locallyScopedConnection.getSession()).execSQL(this, (String)null, maxRowsToRetrieve, (NativePacketPayload)sendPacket, createStreamingResultSet, this.getResultSetFactory(), this.getCurrentCatalog(), metadata, isBatch); 
                        } finally {  
                        }  
    
                    return var10000;
                }
            }  
        }
    public <T extends Resultset> T execSQL(Query callingQuery, String query, int maxRows, NativePacketPayload packet, boolean streamResults, ProtocolEntityFactory<T, NativePacketPayload> resultSetFactory, String catalog, ColumnDefinition cachedMetadata, boolean isBatch) {    
            Resultset var30;
            label222: { 
                try {  
                    var13 = ((NativeProtocol)this.protocol).sendQueryPacket(callingQuery, packet, maxRows, streamResults, catalog, cachedMetadata, this::getProfilerEventHandlerInstanceFunction, resultSetFactory);
                } finally {     
        }
    NativePacketPayload resultPacket = this.sendCommand(queryPacket, false, 0);  //   sendPacket  =    . S E L E C T    c o u n t ( 0 ) F R O M   m o n e y   W H E R  E   i d   =   2  5
    this.send(queryPacket, queryPacket.getPosition());;  //   queryPacket=    . S E L E C T    c o u n t ( 0 ) F R O M   m o n e y   W H E R  E   i d   =   2  5
    this.packetSender.send(packet.getByteBuffer(), packetLen, this.packetSequence);  //   packet=    . S E L E C T    c o u n t ( 0 ) F R O M   m o n e y   W H E R  E   i d   =   2  5
    
    public void send(byte[] packet, int packetLen, byte packetSequence) throws IOException {
            this.packetSender.send(packet, packetLen, packetSequence);
            this.previousPacketSentTime = this.lastPacketSentTime;
            this.lastPacketSentTime = System.currentTimeMillis();
        }
    public void send(byte[] packet, int packetLen, byte packetSequence) throws IOException {
            PacketSplitter packetSplitter = new PacketSplitter(packetLen);
            while(packetSplitter.nextPacket()) {
                this.outputStream.write(NativeUtils.encodeMysqlThreeByteInteger(packetSplitter.getPacketLen()));
                this.outputStream.write(packetSequence++);
                this.outputStream.write(packet, packetSplitter.getOffset(), packetSplitter.getPacketLen());
            }
            this.outputStream.flush();
        }

    对结果集的封装 //把结果集映射成javaBean。

    public List<Object> handleResultSets(Statement stmt) throws SQLException {   
        ResultSetWrapper rsw = getFirstResultSet(stmt);   //把PrapareStatment的ResultSet拿出来,并且包装成ResultSetWrapper 
    
        List<ResultMap> resultMaps = mappedStatement.getResultMaps();  //拿到UserMapper.xml里面的<resultMap>节点,然后做映射。ORM就是做映射。
        int resultMapCount = resultMaps.size();
        validateResultMapsCount(rsw, resultMapCount);
        while (rsw != null && resultMapCount > resultSetCount) {
          ResultMap resultMap = resultMaps.get(resultSetCount);
          handleResultSet(rsw, resultMap, multipleResults, null);
          rsw = getNextResultSet(stmt);
          cleanUpAfterHandlingResultSet();
          resultSetCount++;
        } 
    
        return collapseSingleResultList(multipleResults);   //multipleResults = [com.example.entity.User(25,JAck,100), com.example.entity.User(27,Kackeeee,100)]
      }
    private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
        ResultSet rs = stmt.getResultSet();   //返回org.apache.ibatis.logging.jdbc.ResultSetLogger是ResultSet的代理
        return rs != null ? new ResultSetWrapper(rs, configuration) : null;    //把ResultSet包装成ResultSetWrapper
      }
    public ResultSetWrapper(ResultSet rs, Configuration configuration) throws SQLException {
        super();
        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
        this.resultSet = rs;   //org.apache.ibatis.logging.jdbc.ResultSetLogger
        final ResultSetMetaData metaData = rs.getMetaData();//
        final int columnCount = metaData.getColumnCount();//3,列的数量
        for (int i = 1; i <= columnCount; i++) {
          columnNames.add(configuration.isUseColumnLabel() ? metaData.getColumnLabel(i) : metaData.getColumnName(i));  //列的名称:[id, name, money]
          jdbcTypes.add(JdbcType.forCode(metaData.getColumnType(i)));//列的类型:[INTEGER, VARCHAR, VARCHAR]
          classNames.add(metaData.getColumnClassName(i));//列的类名:[java.lang.Integer, java.lang.String, java.lang.String]
        }
      }
    private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping)  {
        try {
          if (parentMapping != null) { 
          } else {
            if (resultHandler == null) {
              DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
              handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
              multipleResults.add(defaultResultHandler.getResultList());  ////查询的多条记录,放到list里面去。[com.example.entity.User(25,JAck,100), com.example.entity.User(27,Kackeeee,100)]
            } else { 
            }
          }
        } 
      }
    public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)   {
        if (resultMap.hasNestedResultMaps()) {  
        } else {
          handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
        }
      }
    private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)  {
        DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
        skipRows(rsw.getResultSet(), rowBounds);//rowBounds是分页的。Limit是查询几条记录,offset是跳过几天记录。
        while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
          ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
          Object rowValue = getRowValue(rsw, discriminatedResultMap);返回com.example.entity.User(id=25,name=LACK2,money=100)
          storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());//有可能有多条记录,放到一个list里面去,
        }
      }
    private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException {
        if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
          if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) {
            rs.absolute(rowBounds.getOffset());
          }
        } else {
          for (int i = 0; i < rowBounds.getOffset(); i++) {
            rs.next();//跳过几条,mybatis的分页是内存分页,因为ResultSet结果集 已经查询出来了。但是加了PageHelper之后,ResultSet 结果集 就是已经分页的,就是物理分页了。
          }
        }
      }
    public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {
        Set<String> pastDiscriminators = new HashSet<String>();
        Discriminator discriminator = resultMap.getDiscriminator();
        while (discriminator != null) { 
        }
        return resultMap;
      }
    private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
        final ResultLoaderMap lazyLoader = new ResultLoaderMap();
        Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);   //根据resultMap标签的Type创建反射对象class com.example.entity.User。返回com.example.entity.User(id=25,name=LACK2,money=100)
        if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { 
        }
        return rowValue;
      }
    private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
        this.useConstructorMappings = false; // reset previous mapping result
        final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();
        final List<Object> constructorArgs = new ArrayList<Object>();
        Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);  //把结果集映射成javaBean。返回com.example.entity.User(id=25,name=LACK2,money=100)。通过反射创建对象和设置值。
        if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
          final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); 
        }
        this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty(); // set current mapping result
        return resultObject;
      } 
    private void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
        if (parentMapping != null) { 
        } else {
          callResultHandler(resultHandler, resultContext, rowValue);
        }
      }
    private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {
        resultContext.nextResultObject(rowValue);
        ((ResultHandler<Object>) resultHandler).handleResult(resultContext);
      }
    public class DefaultResultHandler implements ResultHandler<Object> {  
      @Override
      public void handleResult(ResultContext<? extends Object> context) {
        list.add(context.getResultObject());//查询的多条记录,放到list里面去。
      } 
    }
  • 相关阅读:
    [翻译]NUnitString && Collection && File && Directory Assert (七)
    c++删除指定字符串之间的内容(比正则表达式快几十倍)[转]
    C++ 使用正则表达式分割字符串
    c++正则查找
    PHP的XSS攻击过滤函数
    Boost之正则表达式_[转]
    C++中的类所占内存空间总结[转]
    make_shared() shared_prt()详解区别
    C++ STRING 和WSTRING 之间的互相转换函数 和字符串替换
    LConfig:利用Lua脚本做程序的配置文件 [转]
  • 原文地址:https://www.cnblogs.com/yaowen/p/12350034.html
Copyright © 2011-2022 走看看