二、Jakarta Commons dbutils:
    用JDBC API時最令人討厭的就是異常處理,也很煩瑣,而且很容易出錯,本人曾考慮過利用模板進行處理,后來看到了dbutils,之后就采用那個dbutils,采用模板的方式各位朋友可以參考Spring,Spring的JdbcTemplate不靈活而強大,呵呵,說句閑話,實在太佩服Rod Johnson了,Rod Johnson真的很令人尊敬。
    Dbutils的QueryRunner把大多數與關閉資源相關的封裝起來,另外,你也可以使用DbUtils進行關閉,當然DbUtils提供的功能當然不止這些,它提過了幾個常用的靜態方法,除了上述的關閉資源外,DbUtils. commitAndClose(Connection conn)還提供事務提及等操作。
還是以一個例子來說說吧,畢竟我不是搞業務的,小嘴巴吧嗒吧噠不起來啊,呵呵。
    為了和采用Beanutils更好的進行對比,這個例子還是實現同樣的功能,數據庫同樣采用前一篇文章中提到的publish。
同樣的,用你喜歡的編輯器建立一個類DbutilsJDBCTest,示例代碼如下所示:
package cn.qtone.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;
public class DbutilsJDBCTest{
    public static void main(String[] args) {
        Connection conn = null;
        String jdbcURL = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
        String jdbcDriver = "com.mysql.jdbc.Driver";
        try {
            DbUtils.loadDriver(jdbcDriver);
            // Username "root". Password "root"
            conn = DriverManager.getConnection(jdbcURL, "root", "root");
            QueryRunner qRunner = new QueryRunner();
            System.out.println("***Using MapListHandler***");
            //以下部分代碼采用Map存儲方式,可以采用Bean的方式代替進行處理
            List lMap = (List) qRunner.query(conn,
                    "select title,authors  from books", new MapListHandler());
            //以下是處理代碼,可以抽取出來
System.out.println("title ------------- authors ");
                for (int i = 0; i < lMap.size(); i++) {
                        Map vals = (Map) lMap.get(i);
                        System.out.println(vals.get("title")+"-------------"+ vals.get("authors"));
                }
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            DbUtils.closeQuietly(conn);
        }
    }
}

怎么樣?是不是比采用Beanutils的ResultSetDynaTrial和RowSetDynaClass好多了?采用Beanutils令人難纏的是關閉那些資源以及處理那些異常,而這里采用Dbutils顯然代碼量減少了很多。
上例在處理結果集時,它把數據庫中的每一行映射成一個Map,其中列名作為Key,該列對應的值作為Value存放,查詢的所有的數據一起放在一個List里,然后進行處理,當然,一個更明智的處理是直接返回List然后再單獨進行處理。
事實上上例返回的結果集中的每一行不必放在一個Map里,你可以放在一個Bean里,當然如果你真的很懶,你也可以使用Beanutils的LazyDynaClass和LazyDynaBean,不過也許沒有必要那么做,至于原因請看下文。

如果使用Bean而不是用Map,那么,你也許需要建立一個Bean,如下:
package cn.qtone.test;
public class Book {
    public int id;
    public String title;
    public String authors ;
    public StudentBean() {
    }
    public String getAuthors() {
        return authors;
    }
    public void setAuthors(String authors) {
        this.authors = authors;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
}

然后簡單修改一下DbutilsJDBCTest 中的部分代碼即可,代替之后的源代碼如下:

package cn.qtone.test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

public class DbutilsJDBCTest{
    public static void main(String[] args) {
        Connection conn = null;
        String jdbcURL = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
        String jdbcDriver = "com.mysql.jdbc.Driver";
        try {
            DbUtils.loadDriver(jdbcDriver);
            // Username "root". Password "root"
            conn = DriverManager.getConnection(jdbcURL, "root", "root");
            QueryRunner qRunner = new QueryRunner();
            System.out.println("***Using BeanListHandler ***");
            //以下部分代碼采用Map存儲方式,可以采用Bean的方式代替進行處理
List lBeans = (List) qRunner.query(conn," select title,authors from books ", new BeanListHandler(Book.class));
    //以下是處理代碼,可以抽取出來
System.out.println("title ------------- authors ");
    for (int i = 0; i < lBeans.size(); i++) {
            Book vals = (Book) lBeans.get(i);    
          System.out.println(vals.getTitle ()+"-------------"+ vals. getAuthors ());
                }
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            DbUtils.closeQuietly(conn);
        }
    }
}
    這兩種法輸出的結果應該是一樣的。兩種處理方式都差不多,但我更愿意采用第一種,因為第一種少寫一個bean,而且我測試過采用Map的方式即第一種方式性能要好的多,采用Bean性能比較低可能是因為采用反射的緣故,采用反射的東東性能和不采用反射的還是有點差距。也是這個原因,不推薦采用LazyDynaClass和LazyDynaBean,因為采用這二者是在運行期動態創建Bean類和Bean屬性,然后再創建Bean對象的,其性能可想而知了(不過我沒有測試過啊,所以我說這個話可說是沒有根據的,感興趣的朋友自己測試一下,記得告訴我結果哦,呵呵),除了MapListHandler以及BeanListHandler之外,DButils還提供了其他的Handler,如果這些不能滿足你的需求,你也可以自己實現一個Handler。
    最后,也是最大的體會,也許是最大的收獲吧,那就是:對于每一個項目,在根據每一個需求獲取相應解決方案時,先尋找開源組件,看是否已經有滿足某些功能需求的開源組件,如果沒有,再考慮自主開發或者向第三方購買,否則盡量采用開源組件.
    請盡量享用開源的魅力,盡情的擁抱開源吧。