深入解析Spring架構與設計原理-數據庫的操作實現-創(chuàng)新互聯

關于Spring JDBC
還是從Spring JDBC說起吧,雖然現在應用很多都是直接使用Hibernate或者其他的ORM工具。但JDBC畢竟還是很基本的,其中的JdbcTemplate就是我們經常使用的,比如JDBCTemplate的execute方法,就是一個基本的方法,在這個方法的實現中,可以看到對數據庫操作的基本過程。

創(chuàng)新互聯公司專注于武川企業(yè)網站建設,響應式網站建設,商城網站制作。武川網站建設公司,為武川等地區(qū)提供建站服務。全流程按需網站策劃,專業(yè)設計,全程項目跟蹤,創(chuàng)新互聯公司專業(yè)和態(tài)度為您提供的服務

//execute方法執(zhí)行的是輸入的sql語句
public void execute(final String sql) throws DataAccessException {
    if (logger.isDebugEnabled()) {
        logger.debug("Executing SQL statement [" + sql + "]");
    }
    class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
        public Object doInStatement(Statement stmt) throws SQLException {
            stmt.execute(sql);
            return null;
        }
        public String getSql() {
            return sql;
        }
    }
    execute(new ExecuteStatementCallback());
}
//這是使用java.sql.Statement處理靜態(tài)SQL語句的方法
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
    Assert.notNull(action, "Callback object must not be null");
    //這里取得數據庫的Connection,這個數據庫的Connection已經在Spring的事務管理之下
    Connection con = DataSourceUtils.getConnection(getDataSource());
    Statement stmt = null;
    try {
        Connection conToUse = con;
        if (this.nativeJdbcExtractor != null &&
                this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
            conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
        }
        //創(chuàng)建Statement
        stmt = conToUse.createStatement();
        applyStatementSettings(stmt);
        Statement stmtToUse = stmt;
        if (this.nativeJdbcExtractor != null) {
            stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
        }
        //這里調用回調函數
        T result = action.doInStatement(stmtToUse);
        handleWarnings(stmt);
        return result;
    }
    catch (SQLException ex) {
        // Release Connection early, to avoid potential connection pool deadlock
        // in the case when the exception translator hasn't been initialized yet.
        //如果捕捉到數據庫異常,把數據庫Connection釋放,同時拋出一個經過Spring轉換過的Spring數據庫異常
        //Spring做了一項有意義的工作,就是把這些數據庫異常統一到自己的異常體系里了
        JdbcUtils.closeStatement(stmt);
        stmt = null;
        DataSourceUtils.releaseConnection(con, getDataSource());
        con = null;
        throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
    }
    finally {
        JdbcUtils.closeStatement(stmt);
        //釋放數據庫connection
        DataSourceUtils.releaseConnection(con, getDataSource());
    }
}

在使用數據庫的時候,有一個很重要的地方就是對數據庫連接的管理,在這里,是由DataSourceUtils來完成的。Spring通過這個輔助類來對數據的Connection進行管理。比如通過它來完成打開和關閉Connection等操作。DataSourceUtils對這些數據庫Connection管理的實現, 如以下代碼所示。

//這是取得數據庫連接的調用,實現是通過調用doGetConnection完成的,這里執(zhí)行了異常的轉換操作
public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
    try {
        return doGetConnection(dataSource);
    }
    catch (SQLException ex) {
        throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex);
    }
}
public static Connection doGetConnection(DataSource dataSource) throws SQLException {
    Assert.notNull(dataSource, "No DataSource specified");
    //把對數據庫的Connection放到事務管理中進行管理,這里使用TransactionSynchronizationManager中定義的ThreadLocal變量來和線程綁定數據庫連接
    //如果在TransactionSynchronizationManager中已經有與當前線程綁定數據庫連接,那就直接取出來使用
    ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
    if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
        conHolder.requested();
        if (!conHolder.hasConnection()) {
            logger.debug("Fetching resumed JDBC Connection from DataSource");
            conHolder.setConnection(dataSource.getConnection());
        }
        return conHolder.getConnection();
    }
    // Else we either got no holder or an empty thread-bound holder here.
    // 這里得到需要的數據庫Connection,在Bean配置文件中定義好的,
    // 同時最后把新打開的數據庫Connection通過TransactionSynchronizationManager和當前線程綁定起來。
    logger.debug("Fetching JDBC Connection from DataSource");
    Connection con = dataSource.getConnection();

    if (TransactionSynchronizationManager.isSynchronizationActive()) {
        logger.debug("Registering transaction synchronization for JDBC Connection");
        // Use same Connection for further JDBC actions within the transaction.
        // Thread-bound object will get removed by synchronization at transaction completion.
        ConnectionHolder holderToUse = conHolder;
        if (holderToUse == null) {
            holderToUse = new ConnectionHolder(con);
        }
        else {
            holderToUse.setConnection(con);
        }
        holderToUse.requested();
        TransactionSynchronizationManager.registerSynchronization(
                new ConnectionSynchronization(holderToUse, dataSource));
        holderToUse.setSynchronizedWithTransaction(true);
        if (holderToUse != conHolder) {
            TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
        }
    }
    return con;
}

關于數據庫操作類RDBMS
從JdbcTemplate中,我們看到,他提供了許多簡單查詢和更新的功能。但是,如果需要更高層次的抽象,以及更面向對象的方法來訪問數據庫,Spring為我們提供了org.springframework.jdbc.object包,里面包含了SqlQuery、SqlMappingQuery、SqlUpdate和StoredProcedure等類,這些類都是Spring JDBC應用程序可以使用的。但要注意,在使用這些類時需要為它們配置好JdbcTemplate作為其基本的操作實現,因為在它們的功能實現中,對數據庫操作的那部分實現基本上還是依賴于JdbcTemplate來完成的。

比如,對MappingSqlQuery使用的過程,是非常簡潔的;在設計好數據的映射代碼之后,查詢得到的記錄已經按照前面的設計轉換為對象List了,一條查詢記錄對應于一個數據對象,可以把數據庫的數據記錄直接映射成Java對象在程序中使用,同時又可避免使用第三方ORM工具的配置,對于簡單的數據映射場合是非常方便的;在mapRow方法的實現中提供的數據轉換規(guī)則,和我們使用Hibernate時,Hibernate的hbm文件起到的作用是非常類似的。這個MappingSqlQuery需要的對設置進行compile,這些compile是這樣完成的,如以下代碼所示:

protected final void compileInternal() {
    //這里是對參數的compile過程,所有的參數都在getDeclaredParameters里面,生成了一個PreparedStatementCreatorFactory
    this.preparedStatementFactory = new PreparedStatementCreatorFactory(getSql(), getDeclaredParameters());
    this.preparedStatementFactory.setResultSetType(getResultSetType());
    this.preparedStatementFactory.setUpdatableResults(isUpdatableResults());
    this.preparedStatementFactory.setReturnGeneratedKeys(isReturnGeneratedKeys());
    if (getGeneratedKeysColumnNames() != null) {
        this.preparedStatementFactory.setGeneratedKeysColumnNames(getGeneratedKeysColumnNames());
    }
his.preparedStatementFactory.setNativeJdbcExtractor(getJdbcTemplate().getNativeJdbcExtractor());
    onCompileInternal();
}

在執(zhí)行查詢時,執(zhí)行的實際上是SqlQuery的executeByNamedParam方法,這個方法需要完成的工作包括配置SQL語句,配置數據記錄到數據對象的轉換的RowMapper,然后使用JdbcTemplate來完成數據的查詢,并啟動數據記錄到Java數據對象的轉換,如以下代碼所示:

public List<T> executeByNamedParam(Map<String, ?> paramMap, Map context) throws DataAccessException {
    validateNamedParameters(paramMap);
    //得到需要執(zhí)行的SQL語句
    ParsedSql parsedSql = getParsedSql();
    MapSqlParameterSource paramSource = new MapSqlParameterSource(paramMap);
    String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
    //配置好SQL語句需要的Parameters及rowMapper,這個rowMapper完成數據記錄到對象的轉換
    Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, getDeclaredParameters());
    RowMapper<T> rowMapper = newRowMapper(params, context);
    //我們又看到了JdbcTemplate,這里使用JdbcTemplate來完成對數據庫的查詢操作,所以我們說JdbcTemplate是非?;镜牟僮黝?br />        return getJdbcTemplate().query(newPreparedStatementCreator(sqlToUse, params), rowMapper);
}

在Spring對JDBC的操作中,基本上是對JDBC/Hibernate基礎上API的封裝。這些封裝可以直接使用,也可以在IoC容器中配置好了再使用,當結合IoC容器的基礎上進行使用的時候,可以看到許多和事務管理相關的處理部分,都是非常值得學習的,在那里,可以看到對數據源的管理 - Hibernate中session的管理,與線程的結合等等。

更多內容請關注微信公眾號:IT哈哈(it_haha)

深入解析Spring架構與設計原理-數據庫的操作實現

另外有需要云服務器可以了解下創(chuàng)新互聯cdcxhl.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。

文章題目:深入解析Spring架構與設計原理-數據庫的操作實現-創(chuàng)新互聯
URL分享:http://muchs.cn/article2/dhicic.html

成都網站建設公司_創(chuàng)新互聯,為您提供軟件開發(fā)外貿網站建設、網站改版做網站、自適應網站、企業(yè)網站制作

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

成都做網站