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:\Code\mybatis\springBoot_Mybatis-master\springBoot_Mybatis-master\Springboot_Mybatis\target\classes\mapping\UserMapper.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里面去。 } }