暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

002 - executeQuery方法执行过程

博博JAVA学习之路 2021-02-17
1062

PreparedStatement.executeQuery()方法执行过程

1. executeQuery()方法调用代码

    // executeQuery()方法调用方式
    String sql = "select id, name, password, is_delete, create_by, create_time, modify_by, modify_time from user where name like concat_ws('', '%', ?,'%')";
    log.info("== sql = " + sql);
    Connection conn = jdbcUtil.getConnection();
    PreparedStatement ps = conn.prepareStatement(sql);
    ps.setString(1, username);
    ResultSet rs = ps.executeQuery();

    2. executeQuery()方法执行过程

    PreparedStatement是一个接口,以上代码使用的是ClientPreparedStatement实现类

      /**
      * Executes the SQL query in this <code>PreparedStatement</code> object
      * and returns the <code>ResultSet</code> object generated by the query.
      *
      * -- 在PreparedStatement对象中执行SQL查询,并返回查询生成的ResultSet对象
      *
      * @return a <code>ResultSet</code> object that contains the data produced by the
      * query; never <code>null</code>
      * @exception SQLException if a database access error occurs;
      * this method is called on a closed <code>PreparedStatement</code> or the SQL
      * statement does not return a <code>ResultSet</code> object
      * @throws SQLTimeoutException when the driver has determined that the
      * timeout value that was specified by the {@code setQueryTimeout}
      * method has been exceeded and has at least attempted to cancel
      * the currently running {@code Statement}
      */
      @Override
      public java.sql.ResultSet executeQuery() throws SQLException {
      // bobo 进入同步代码块中,
      // connection 是否已经关闭
      synchronized (checkClosed().getConnectionMutex()) {
      // bobo 本方法中connection对象
      JdbcConnection locallyScopedConn = this.connection;


      // bobo 校验是否是dml的sql语句
      /**
      * - 校验是否是dml的sql语句
      * - 先判断首字母是否是由I,U,D,A,C,T,R字母开始,即
      * I - INSERT - 插入
      * U - UPDATE - 更新
      * D - DELETE、DROP - 删除数据、删除表
      * A - ALTER - 修改表
      * C - CREATE - 创建表、数据库
      * T - TRUNCATE - 删除表所有记录
      * R - RENAME - 重命名
      * - 如果是以上任意一种,抛异常 SQLException
      */
      checkForDml(((PreparedQuery<?>) this.query).getOriginalSql(), ((PreparedQuery<?>) this.query).getParseInfo().getFirstStmtChar());


      // bobo 初始化批量生成主键key
      this.batchedGeneratedKeys = null;


      // bobo 重置取消状态
      resetCancelledState();


      // bobo 立刻关闭所有结果集
      /**
      * Close all result sets in this statement. This includes multi-results
      * - 关闭此语句中的所有结果集。这包括multi-results
      * @throws SQLException
      */
      implicitlyCloseAllOpenResults();


      // bobo 清除所有警告
      clearWarnings();


      // bobo ping 服务器,是否可以了解
      /**
      * Detect if the connection is still good by sending a ping command to the server.
      * - 通过向服务器发送ping命令来检测连接是否仍然有效
      */
      if (this.doPingInstead) {
      doPingInstead();


      return this.results;
      }


      // bobo 设置流的超时时间
      setupStreamingTimeout(locallyScopedConn);


      // bobo 拼接sql语句,将参数匹配到对应?位置处
      Message sendPacket = ((PreparedQuery<?>) this.query).fillSendPacket();


      // bobo 初始化数据库
      String oldDb = null;


      if (!locallyScopedConn.getDatabase().equals(this.getCurrentDatabase())) {
      oldDb = locallyScopedConn.getDatabase();
      locallyScopedConn.setDatabase(this.getCurrentDatabase());
      }


      //
      // Check if we have cached metadata for this query...
      //
      // bobo 检查是否缓存了此查询的元数据
      // bobo 缓存的结果集
      CachedResultSetMetaData cachedMetadata = null;
      boolean cacheResultSetMetadata = locallyScopedConn.getPropertySet().getBooleanProperty(PropertyKey.cacheResultSetMetadata).getValue();


      // bobo select id, name, password, is_delete, create_by, create_time, modify_by, modify_time from user where name like concat_ws('', '%', ?,'%')
      // bobo 源sql语句,即带有占位符的sql语句
      String origSql = ((PreparedQuery<?>) this.query).getOriginalSql();


      // bobo 是否缓存了数据
      if (cacheResultSetMetadata) {
      // bobo 获取缓存的数据
      cachedMetadata = locallyScopedConn.getCachedMetaData(origSql);
      }


      // bobo 初始化行数
      locallyScopedConn.setSessionMaxRows(this.maxRows);


      // bobo 执行sql语句,返回执行后的结果集
      /**
      * - 获取结果集
      * - 存放在 result.rowData.rows字节数组中
      */
      this.results = executeInternal(this.maxRows, sendPacket, createStreamingResultSet(), true, cachedMetadata, false);


      if (oldDb != null) {
      locallyScopedConn.setDatabase(oldDb);
      }


      // bobo 缓存中有数据,则将缓存中数据赋值给结果集
      if (cachedMetadata != null) {
      locallyScopedConn.initializeResultsMetadataFromCache(origSql, cachedMetadata, this.results);
      } else {
      // bobo 是否创建缓存数据,将得到的结果集数据添加到缓存中
      if (cacheResultSetMetadata) {
      locallyScopedConn.initializeResultsMetadataFromCache(origSql, null /* will be created */, this.results);
      }
      }


      // bobo 这个结果集返回的auto_increment的值,即自增主键的值
      this.lastInsertId = this.results.getUpdateID();


      // bobo 返回获取的结果集
      return this.results;
      }
      }

      主要执行sql语句,获取数据的代码如下

        /**
        * -- 在PreparedStatement对象中执行SQL查询,并返回查询生成的ResultSet对象
        */
        @Override
        public java.sql.ResultSet executeQuery() throws SQLException {
        // bobo 进入同步代码块中,
        // connection 是否已经关闭
        synchronized (checkClosed().getConnectionMutex()) {

        ··· ···

        // bobo 拼接sql语句,将参数匹配到对应?位置处
        Message sendPacket = ((PreparedQuery<?>) this.query).fillSendPacket();


        ··· ···

        // bobo 执行sql语句,返回执行后的结果集
        /**
        * - 获取结果集
        * - 存放在 result.rowData.rows字节数组中
        */
        this.results = executeInternal(this.maxRows, sendPacket, createStreamingResultSet(), true, cachedMetadata, false);


        ··· ···


        // bobo 返回获取的结果集
        return this.results;
        }
        }


        文章转载自博博JAVA学习之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

        评论