mysql jdbc驱动源码分析(获取Statement对象)

在前面的文章中我们分析了获取Connection 对象的代码,下面来看看获取Statement的源码:

ConnectionImpl类的createStatement() 方法获取Statement实例

 // 获取Statement对象,没有参数则使用默认的参数
    public java.sql.Statement createStatement() throws SQLException {
		// 这里的默认值就是在获得ResultSet的值后,不能滚动只能向后移动
        return createStatement(DEFAULT_RESULT_SET_TYPE, DEFAULT_RESULT_SET_CONCURRENCY);
    }


指定了该对象将生成具有给定类型和并发性的 ResultSet 对象。
  public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
        checkClosed();
        // StatementImpl 的两个参数,一个是当前数据库的链接Connection 一个是当前用的数据库
        StatementImpl stmt = new StatementImpl(getMultiHostSafeProxy(), this.database);
        stmt.setResultSetType(resultSetType);
        stmt.setResultSetConcurrency(resultSetConcurrency);
        // 创建statement对象。
        return stmt;
    }
其中的checkClosed() 方法就是检测Connection 链接有没有断开或关闭。


StatementImpl对象的获取从上面的代码中能看到是创建了一个<span style="font-family: Arial, Helvetica, sans-serif;">StatementImpl对象,</span><span style="font-family: Arial, Helvetica, sans-serif;">StatementImpl 构造函数源码如下:</span>

 /**
     * Constructor for a Statement.
     * 
     * @param c
     *            the Connection instantation that creates us
     * @param catalog
     *            the database name in use when we were created
     * 
     * @throws SQLException
     *             if an error occurs.
     */
    public StatementImpl(MySQLConnection c, String catalog) throws SQLException {
		//判断当前的链接有没有断开,如果为空或是断开了则抛出异常
        if ((c == null) || c.isClosed()) {
            throw SQLError.createSQLException(Messages.getString("Statement.0"), SQLError.SQL_STATE_CONNECTION_NOT_OPEN, null);
        }

        this.connection = c;
        this.connectionId = this.connection.getId();
        this.exceptionInterceptor = this.connection.getExceptionInterceptor();

        this.currentCatalog = catalog;
        this.pedantic = this.connection.getPedantic();
        this.continueBatchOnError = this.connection.getContinueBatchOnError();
        this.useLegacyDatetimeCode = this.connection.getUseLegacyDatetimeCode();
        this.sendFractionalSeconds = this.connection.getSendFractionalSeconds();
        this.doEscapeProcessing = this.connection.getEnableEscapeProcessing();

        if (!this.connection.getDontTrackOpenResources()) {
            this.connection.registerStatement(this);
        }

        this.maxFieldSize = this.connection.getMaxAllowedPacket();

        int defaultFetchSize = this.connection.getDefaultFetchSize();
        if (defaultFetchSize != 0) {
            setFetchSize(defaultFetchSize);
        }

        if (this.connection.getUseUnicode()) {
            this.charEncoding = this.connection.getEncoding();
            this.charConverter = this.connection.getCharsetConverter(this.charEncoding);
        }

        boolean profiling = this.connection.getProfileSql() || this.connection.getUseUsageAdvisor() || this.connection.getLogSlowQueries();
        if (this.connection.getAutoGenerateTestcaseScript() || profiling) {
            this.statementId = statementCounter++;
        }
        if (profiling) {
            this.pointOfOrigin = LogUtils.findCallingClassAndMethod(new Throwable());
            this.profileSQL = this.connection.getProfileSql();
            this.useUsageAdvisor = this.connection.getUseUsageAdvisor();
            this.eventSink = ProfilerEventHandlerFactory.getInstance(this.connection);
        }

        int maxRowsConn = this.connection.getMaxRows();
        if (maxRowsConn != -1) {
            setMaxRows(maxRowsConn);
        }

        this.holdResultsOpenOverClose = this.connection.getHoldResultsOpenOverStatementClose();

        this.version5013OrNewer = this.connection.versionMeetsMinimum(5, 0, 13);
    }

到这里StatementImpl 对象就创建了,从构造函数我们可以看出,创建的过程就是设置了一些结果集展示的属性,如最大行数,字符编码等,不管设置什么属性他们都是依赖于当前的链接即Connectio 对象的,如果Connection为null 或者链接被关闭了则会报异常,即null 或者SQLError.SQL_STATE_CONNECTION_NOT_OPEN 所以,创建Statement对象的基础是要有Connection。还有如果有空闲的Statement我们可以重用,不用再次创建Statement对象。





展开阅读全文

没有更多推荐了,返回首页