首頁  >  文章  >  Java  >  DataSourceUitls的介紹及方法

DataSourceUitls的介紹及方法

零下一度
零下一度原創
2017-07-26 17:01:351795瀏覽

DataSourceUitls介紹

DataSourceUitls類別位於org.springframework.jdbc.datasource套件下,提供了很多的靜態方法去從一個javax.sql.DataSource下取得JDBC Connection,並且提供了對Spring 事務管理的支持。

在JdbcTemplate類別的內部,DataSourceUtils被多次使用。其實,我們還可以在程式碼中直接使用DataSourceUitls來操作Jdbc。

DataSourceUitls取得Connection

getConnection方法

內部實作

    public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
        try {
            return doGetConnection(dataSource);
        }
        catch (SQLException ex) {
            throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex);
        }
        catch (IllegalStateException ex) {
            throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection: " + ex.getMessage());
        }
    }

可以看出,透過傳入一個指定的DataSource,可以取得一個Connection,取得過程由doGetConnection方法實作。如果拋出SQLException和IllegalStateException,則將其包裝成CannotGetJdbcConnectionException,事實上也只能拋出SQLException和IllegalStateException這兩種例外。透過檢視CannotGetJdbcConnectionException的原始碼,我們可以發現CannotGetJdbcConnectionException實際上是DataAccessException的子類,因此可以說,getConnection會將拋出的異常統一封裝成Spring的DataAccessException。

doGetConnection方法

內部實作

    public static Connection doGetConnection(DataSource dataSource) throws SQLException {
        Assert.notNull(dataSource, "No DataSource specified");

        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(fetchConnection(dataSource));
            }
            return conHolder.getConnection();
        }
        // Else we either got no holder or an empty thread-bound holder here.

        logger.debug("Fetching JDBC Connection from DataSource");
        Connection con = fetchConnection(dataSource);

        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;
    }

doGetConnection方法是用來實際操作取得Connection的核心方法。從原始程式碼可以得出,如果不存在與目前執行緒綁定的Connection,則新建一個全新的Connection,如果當前執行緒的事務同步處於活動狀態,那麼為剛剛建立的Connection新增Spring事務管理的支援;如果當前執行緒存在一個對應的Connection,那麼則有目前的事務管理分配。

fetchConnection方法

fetchConnection是private方法,不對外公開,實際上是做了一個簡單的功能:從目前的DastaSource新建一個Connection,如果新建失敗,那麼拋出IllegalStateException ,提示不能取得一個新的Connection。

DataSourceUitls釋放Connection

releaseConnection方法

內部實作

    public static void releaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) {
        try {
            doReleaseConnection(con, dataSource);
        }
        catch (SQLException ex) {
            logger.debug("Could not close JDBC Connection", ex);
        }
        catch (Throwable ex) {
            logger.debug("Unexpected exception on closing JDBC Connection", ex);
        }
    }

releaseConnection方法的具體實作由doReleaseConnection處理。如果拋出異常,只是在日誌中做debug處理,不會對外拋出。此方法的兩個參數都存在NULL的情況,
如果con為NULL,則忽略本次呼叫;而另一個參數則被允許為NULL。

doReleaseConnection方法

內部實作

    public static void doReleaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) throws SQLException {
        if (con == null) {
            return;
        }
        if (dataSource != null) {
            ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
            if (conHolder != null && connectionEquals(conHolder, con)) {
                // It's the transactional Connection: Don't close it.
                conHolder.released();
                return;
            }
        }
        logger.debug("Returning JDBC Connection to DataSource");
        doCloseConnection(con, dataSource);
    }

doReleaseConnection方法是真正釋放了Connection的方法,與releaseConnection方法相比,則完成了傳入的兩個參數的校驗和拋出更底層的異常。在dataSource不為NULL的情況下,釋放此ConnectionHolder保留的目前連接,使得該目前的Connection可以得到重複使用,對提供Jdbc操作的效能很有幫助。如果dataSource為null的情況下則選擇直接關閉連線。

DataSourceUitls關閉Connection

doCloseConnection方法

內部實作

    public static void doCloseConnection(Connection con, @Nullable DataSource dataSource) throws SQLException {
        if (!(dataSource instanceof SmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {
            con.close();
        }
    }

在doReleaseConnection方法中,我們已經得知datasource為NULL的時候會執行doCloseConnection方法。事實上,只有dataSource沒有實作org.springframework.jdbc.datasource.SmartDataSource介面的時候或是dataSource實作了org.springframework.jdbc.datasource.SmartDataSource介面且允許關閉的時候,在真正關閉了Connection。

org.springframework.jdbc.datasource.SmartDataSource介面是 javax.sql.DataSource介面的一個擴展,用一種未包裝的形式傳回Jdbc的連接。實作該介面的類別可以查詢Connection在完成操作之後是否應該關閉。在Srping和DataSourceUitls和JdbcTemplate中會自動執行這樣的檢查。

以上是DataSourceUitls的介紹及方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn