Spring JDBC最佳實踐

openkk 12年前發布 | 99K 次閱讀 Spring JEE框架 Spring JDBC

Spring提供了兩種使用JDBC API的最佳實踐,一種是以JdbcTemplate為核心的基于Template的JDBC的使用方式,另一種則是在JdbcTemplate基礎之上的構建的基于操作對象的JDBC的使用方式。

基于Template的JDBC的使用方式
該使用方式的最初設想和原型,需要追溯到Rod Johnson在03年出版的Expert One-on-One J2EE Design and Development,在該書的Practical Data Access(數據訪問實踐)中,Rod針對JDBC使用中的一些問題提出了一套改進的實踐原型,并最終將該原型完善后在Spring框架中發布。

JDBC的尷尬
JDBC作為Java平臺的訪問關系數據庫的標準,其成功是 有目共睹的。幾乎所有java平臺的數據訪問,都直接或者間接的使用了JDBC,它是整個java平臺面向關系數據庫進行數據訪問的基石。
作為一個標準,無疑JDBC是很成功的,但是要說JDBC在使用過程當中多么的受人歡迎,則不盡然了。JDBC主要是面向較為底層的數據庫操作,所以在設計的過程當中 ,比較的貼切底層以提供盡可能多的功能特色。從這個角度來說,JDBC API的設計無可厚非。可是,過于貼切底層的API的設計,對于開發人員則未必是一件好事。即使執行一個最簡單的查詢,開發人員也要按照API的規矩寫上一大堆雷同的代碼,如果不能合理的封裝使用JDBC API,在項目中使用JDBC訪問數據所出現的問題估計會使人發瘋!
對于通常的項目開發來說,如果層次劃分很明確,數據訪問邏輯一般應該在DAO層中實現。根據功能模塊的劃分,可能每個開發人員都會分得或多或少的實現相應的DAO的任務,假設開發人員A在分得了DAO實現任務后進行開發,他或許開發了如下所示的代碼:

package com.google.spring.jdbc;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class DaoWithA implements IDao
{

    private final Log logger = LogFactory.getLog(DaoWithA.class);
    private DataSource dataSource = null;

    public DataSource getDataSource()
    {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource)
    {
        this.dataSource = dataSource;
    }

    @Override
    public int updateSomething(String sql)
    {
        int count;
        Connection conn = null;
        Statement stmt = null;
        try
        {
            conn = getDataSource().getConnection();
            stmt = conn.createStatement();
            count = stmt.executeUpdate(sql);
            stmt.close();
            stmt = null;
        } 
        catch (SQLException e)
        {
            throw new RuntimeException(e);

        }
        finally
        {
            if(stmt!=null)
            {
                try
                {
                    stmt.close();
                } 
                catch (SQLException ex)
                {
                    logger.warn("fail to close statement:"+ex);
                }
            }
            if(conn!=null)
            {
                try
                {
                    conn.close();
                } 
                catch (Exception ex)
                {
                    logger.warn("failed to close Connection:"+ex);
                }
            }
        }
        return count;
    }

}

而B所負責的DAO的實現中,可能也有類似的更新的操作。無疑,B也要像A這樣,在他的DAO實現類中寫一大堆同樣的JDBC代碼,類似的情況還可能擴展到C、D等開發人員。如果每個開發人員都能嚴格的按照JDBC的編程規范開發還好,但是事實是,一個團隊中的開發人員是有差別的。
這其實只是API的使用過程中的一個插曲,當你看到應用程序中成百的使用JDBC實現類的時候,會發現如下的問題:
1、Statement使用完沒有關閉,而是想著讓Connection關閉的時候一并關閉,可是并非所有的驅動程序都有這樣的行為。
2、創建了多個ResultSet或者Statement,只清理了最外層的,忽視了里層的。

3、忘記關閉Connection。
JDBC規范在指定數據庫訪問異常的時候也沒有能夠進行的很徹底:
1、將異常類型定義為SQLException是一個值得商榷的地方。
2、SQLExcpetion沒有采用將具體的異常情況子類化,以進一步抽象不同的數據訪問的情況,而是采用ErrorCode的方式來區分訪問過程中所出現的不同異常情況,其實這也沒什么,只要能區分出具體的錯誤就行,但是JDBC規范卻把ErrorCode的規范留給了數據庫提供商,這導致了不同的數據庫供應商對應了不同的ErrorCode,進而應用程序在捕獲到SQLException后,還要看當前用的是什么數據庫。
針對以上問題,Spring提供了相應的解決方案幫助我們提高開發效率!

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!