Dict.CN 在線詞典, 英語學(xué)習(xí), 在線翻譯

          都市淘沙者

          荔枝FM Everyone can be host

          統(tǒng)計(jì)

          留言簿(23)

          積分與排名

          優(yōu)秀學(xué)習(xí)網(wǎng)站

          友情連接

          閱讀排行榜

          評論排行榜

          利用Jakarta Commons組件beanutils、dbutils簡化JDBC數(shù)據(jù)庫操作(轉(zhuǎn))

          關(guān)鍵字:beanutils、dbutils、JDBC 數(shù)據(jù)庫
          摘要:本文簡單介紹了Jakarta Commons旗下beanutils、dbutils在基于JDBC API數(shù)據(jù)庫存取操作中的運(yùn)用。
              雖然現(xiàn)在出現(xiàn)了很多ORM框架,可是還是有很多朋友也許還在使用JDBC,就像我現(xiàn)在一樣,除了學(xué)習(xí)的時(shí)候在使用Hibernate、Spring類似這些優(yōu)秀的框架,工作時(shí)一直都在使用JDBC。本文就簡單介紹一下利用Jakarta Commons旗下beanutils、dbutils簡化JDBC 數(shù)據(jù)庫操作,以拋磚引玉,希望對像我一樣在使用JDBC的朋友有所幫助。
              下面就分兩部分簡單介紹beanutils、dbutils在基于JDBC API數(shù)據(jù)庫存取操作中的運(yùn)用。第一部分顯介紹beanutils在JDBC數(shù)據(jù)庫存取操作中的運(yùn)用,第二部分介紹dbutils在JDBC 數(shù)據(jù)庫存取操作中的運(yùn)用,最后看看他們的優(yōu)缺點(diǎn),談?wù)劚救嗽陧?xiàng)目運(yùn)用過程中對他們的一點(diǎn)心得體會,僅供參考,其中有錯(cuò)誤的地方希望大蝦不吝賜教,大家多多交流共同進(jìn)步。
          一、Jakarta Commons beanutils
              Beanutils是操作Bean的銳利武器,其提過的 BeanUtils工具類可以簡單方便的讀取或設(shè)置Bean的屬性,利用Dyna系列,還可以在運(yùn)行期創(chuàng)建Bean,符合懶人的習(xí)慣,正如 LazyDynaBean,LazyDynaClass一樣,呵呵。這些用法已經(jīng)有很多文章提及,也可以參考apache的官方文檔。
              對于直接利用JDBC API訪問數(shù)據(jù)庫時(shí)(這里針對的是返回結(jié)果集ResultSet的查詢select),大多數(shù)都是采用兩種方式,一種是取出返回的結(jié)果集的數(shù)據(jù)存于Map中,另一種方式是Bean里。針對第二種方式,Beanutils里提供了ResultSetDynaClass結(jié)合 DynaBean以及RowSetDynaClass結(jié)合DynaBean來簡化操作。下面用以個(gè)簡單的例子展示一下beanutils的這兩個(gè)類在 JDBC數(shù)據(jù)庫操作中的運(yùn)用。
              請?jiān)诒緳C(jī)建立數(shù)據(jù)庫publish,我用的是MySQL,在publish數(shù)據(jù)庫中建立表book,腳本如下:
          1CREATE TABLE book(
          2  id int(11NOT NULL auto_increment,
          3  title varchar(50character set latin1 NOT NULL,
          4  authors varchar(50character set latin1 default NULL
          5  PRIMARY KEY  (id)
          6


               然后用你喜歡的編輯器建立一個(gè)類BeanutilsJDBCTest,我們先用ResultSetDynaClass來處理,然后再用 RowSetDynaClass來實(shí)現(xiàn)同樣的類,之后看看他們之間有什么不同,用ResultSetDynaClass處理的源代碼如下所示:
               然后用你喜歡的編輯器建立一個(gè)類BeanutilsJDBCTest,我們先用ResultSetDynaClass來處理,然后再用 RowSetDynaClass來實(shí)現(xiàn)同樣的類,之后看看他們之間有什么不同,用ResultSetDynaClass處理的源代碼如下所示:
           1package cn.qtone.test;
           2
           3import java.sql.Connection;
           4import java.sql.DriverManager;
           5import java.sql.ResultSet;
           6import java.sql.Statement;
           7import java.util.Iterator; 
           8import org.apache.commons.beanutils.DynaBean;
           9import org.apache.commons.beanutils.PropertyUtils;
          10import org.apache.commons.beanutils.ResultSetDynaClass; 
          11public class BeanutilsJDBCTest{
          12       public static void main(String[] args) {
          13              Connection con = null;
          14              Statement st = null;
          15              ResultSet rs = null;
          16              try {
          17                     Class.forName("com.mysql.jdbc.Driver");
          18                     String url = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
          19                     con = DriverManager.getConnection(url, "root""hyys");
          20                     st = con.createStatement();
          21                     rs = st.executeQuery("select * from book");
          22                     ResultSetDynaClass rsDynaClass = new ResultSetDynaClass(rs);
          23                     Iterator itr = rsDynaClass.iterator();
          24                     System.out.println("title-------------authors");
          25                     while (itr.hasNext()) {
          26                            DynaBean dBean = (DynaBean) itr.next();
          27                            System.out.println(PropertyUtils.getSimpleProperty(dBean,"title")+ "-------"+ PropertyUtils.getSimpleProperty(dBean, "authors"));
          28
          29                     }

          30              }
           catch (Exception e) {
          31                     e.printStackTrace();
          32              }
           finally {
          33                     try {
          34                            if (rs != null{
          35                                   rs.close();
          36                            }

          37                            if (st != null{
          38                                   st.close();
          39                            }

          40                            if (con != null{
          41                                   con.close();
          42                            }

          43                     }
           catch (Exception e) {
          44                            e.printStackTrace();
          45                     }

          46              }

          47       }

          48}
           
          49

          用RowSetDynaClass處理的源代碼如下所示: 

           1package cn.qtone.test; 
           2
           3import java.sql.Connection;
           4import java.sql.DriverManager;
           5import java.sql.ResultSet;
           6import java.sql.Statement;
           7import java.util.Iterator;
           8import java.util.List; 
           9import org.apache.commons.beanutils.DynaBean;
          10import org.apache.commons.beanutils.PropertyUtils;
          11import org.apache.commons.beanutils.RowSetDynaClass; 
          12
          13public class BeanutilsJDBCTest{
          14       public static void main(String[] args) {
          15              List rsDynaClass = rsTest();
          16              System.out.println("title ------------- authors ");
          17              Iterator itr = rsDynaClass.iterator();
          18              while (itr.hasNext()) {
          19                     DynaBean dBean = (DynaBean) itr.next();
          20                     try {
          21                            System.out.println(PropertyUtils.getSimpleProperty(dBean,"name")  + "-----"+ PropertyUtils.getSimpleProperty(dBean, "mobile"));
          22                     }
           catch (Exception e) {
          23                            // TODO 自動生成 catch 塊
          24                            e.printStackTrace();
          25                     }

          26              }

          27       }
           
          28       private static List rsTest() {
          29              Connection con = null;
          30              Statement st = null;
          31              ResultSet rs = null;
          32              try {
          33                     Class.forName("com.mysql.jdbc.Driver");
          34                     String url = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
          35                     con = DriverManager.getConnection(url, "root""hyys");
          36                     st = con.createStatement();
          37                     rs = st.executeQuery("select * from book");
          38                     RowSetDynaClass rsdc = new RowSetDynaClass(rs);
          39                     return rsdc.getRows();
          40              }
           catch (Exception e) {
          41                     e.printStackTrace();
          42              }
           finally {
          43                     try {
          44                            if (rs != null{
          45                                   rs.close();
          46                            }

          47                            if (st != null{
          48                                   st.close();
          49                            }

          50                            if (con != null{
          51                                   con.close();
          52                            }

          53                     }
           catch (Exception e) {
          54                            e.printStackTrace();
          55                     }

          56              }

          57              return null;
          58       }

          59}
           



               這兩個(gè)方法輸出的結(jié)果應(yīng)該是一樣的。但是很顯然第二種方式比第一種方式要好,它把數(shù)據(jù)訪問部分抽取出來放到一個(gè)方法中,顯得簡單清晰。
                其實(shí)在利用ResultSetDynaClass時(shí),必須在ResultSet等數(shù)據(jù)庫資源關(guān)閉之前,處理好那些數(shù)據(jù),你不能在資源關(guān)閉之后使用 DynaBean,否則就會拋出異常,異常就是說不能在ResultSet之后存取數(shù)據(jù)(具體的異常名我也忘了),當(dāng)然你也可以采用以前的方式一個(gè)一個(gè)的把數(shù)據(jù)放到Map里,如果你一定要那樣做,建議還是別用Beanutils,因?yàn)檫@沒帶給你什么好處。總之利用ResultSetDynaClass你的程序的擴(kuò)展性非常部好。
              從第二中方式可以看出,利用RowSetDynaClass可以很好的解決上述 ResultSetDynaClass遇到的問題,RowSetDynaClass的getRows()方法,把每一行封裝在一個(gè)DynaBean對象里,然后,把說有的行放到一個(gè)List里,之后你就可以對返回的List里的每一個(gè)DynaBean進(jìn)行處理,此外對于DynaBean你還可以采用標(biāo)準(zhǔn)的get/set方式處理,當(dāng)然你也可以用PropertyUtils. getSimpleProperty(Object bean,  String name)進(jìn)行處理。
              從上面的分析中,你應(yīng)該可以決定你應(yīng)該使用ResultSetDynaClass還是RowSetDynaClass了。

          二、Jakarta Commons dbutils:
               用JDBC API時(shí)最令人討厭的就是異常處理,也很煩瑣,而且很容易出錯(cuò),本人曾考慮過利用模板進(jìn)行處理,后來看到了dbutils,之后就采用那個(gè) dbutils,采用模板的方式各位朋友可以參考Spring,Spring的JdbcTemplate不靈活而強(qiáng)大,呵呵,說句閑話,實(shí)在太佩服 Rod Johnson了,Rod Johnson真的很令人尊敬。
              Dbutils的QueryRunner把大多數(shù)與關(guān)閉資源相關(guān)的封裝起來,另外,你也可以使用DbUtils進(jìn)行關(guān)閉,當(dāng)然DbUtils提供的功能當(dāng)然不止這些,它提過了幾個(gè)常用的靜態(tài)方法,除了上述的關(guān)閉資源外, DbUtils. commitAndClose(Connection conn)還提供事務(wù)提及等操作。
          還是以一個(gè)例子來說說吧,畢竟我不是搞業(yè)務(wù)的,小嘴巴吧嗒吧噠不起來啊,呵呵。
              為了和采用Beanutils更好的進(jìn)行對比,這個(gè)例子還是實(shí)現(xiàn)同樣的功能,數(shù)據(jù)庫同樣采用前一篇文章中提到的publish。
          同樣的,用你喜歡的編輯器建立一個(gè)類DbutilsJDBCTest,示例代碼如下所示:

           1package cn.qtone.test;
           2import java.sql.Connection;
           3import java.sql.DriverManager;
           4import java.sql.SQLException;
           5import java.util.List;
           6import java.util.Map;
           7import org.apache.commons.dbutils.DbUtils;
           8import org.apache.commons.dbutils.QueryRunner;
           9import org.apache.commons.dbutils.handlers.MapListHandler;
          10public class DbutilsJDBCTest{
          11    public static void main(String[] args) {
          12        Connection conn = null;
          13        String jdbcURL = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
          14        String jdbcDriver = "com.mysql.jdbc.Driver";
          15        try {
          16            DbUtils.loadDriver(jdbcDriver);
          17            // Username "root". Password "root"
          18            conn = DriverManager.getConnection(jdbcURL, "root""root");
          19            QueryRunner qRunner = new QueryRunner();
          20            System.out.println("***Using MapListHandler***");
          21            //以下部分代碼采用Map存儲方式,可以采用Bean的方式代替進(jìn)行處理
          22            List lMap = (List) qRunner.query(conn,
          23                    "select title,authors  from books"new MapListHandler());
          24            //以下是處理代碼,可以抽取出來
          25System.out.println("title ------------- authors ");
          26                for (int i = 0; i < lMap.size(); i++{
          27                        Map vals = (Map) lMap.get(i);
          28                        System.out.println(vals.get("title")+"-------------"+ vals.get("authors"));
          29                }

          30        }
           catch (SQLException ex) {
          31            ex.printStackTrace();
          32        }
           finally {
          33            DbUtils.closeQuietly(conn);
          34        }

          35    }

          36}



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

          如果使用Bean而不是用Map,那么,你也許需要建立一個(gè)Bean,如下:

           1package cn.qtone.test;
           2public class Book {
           3    public int id;
           4    public String title;
           5    public String authors ;
           6    public StudentBean() {
           7    }

           8    public String getAuthors() {
           9        return authors;
          10    }

          11    public void setAuthors(String authors) {
          12        this.authors = authors;
          13    }

          14    public int getId() {
          15        return id;
          16    }

          17    public void setId(int id) {
          18        this.id = id;
          19    }

          20    public String getTitle() {
          21        return title;
          22    }

          23    public void setTitle(String title) {
          24        this.title = title;
          25    }

          26}



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

           1package cn.qtone.test;
           2
           3import java.sql.Connection;
           4import java.sql.DriverManager;
           5import java.sql.SQLException;
           6import java.util.List;
           7import java.util.Map;
           8import org.apache.commons.dbutils.DbUtils;
           9import org.apache.commons.dbutils.QueryRunner;
          10import org.apache.commons.dbutils.handlers.BeanListHandler;
          11
          12public class DbutilsJDBCTest{
          13    public static void main(String[] args) {
          14        Connection conn = null;
          15        String jdbcURL = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
          16        String jdbcDriver = "com.mysql.jdbc.Driver";
          17        try {
          18            DbUtils.loadDriver(jdbcDriver);
          19            // Username "root". Password "root"
          20            conn = DriverManager.getConnection(jdbcURL, "root""root");
          21            QueryRunner qRunner = new QueryRunner();
          22            System.out.println("***Using BeanListHandler ***");
          23            //以下部分代碼采用Map存儲方式,可以采用Bean的方式代替進(jìn)行處理
          24List lBeans = (List) qRunner.query(conn," select title,authors from books "new BeanListHandler(Book.class));
          25    //以下是處理代碼,可以抽取出來
          26System.out.println("title ------------- authors ");
          27    for (int i = 0; i < lBeans.size(); i++{
          28            Book vals = (Book) lBeans.get(i);    
          29          System.out.println(vals.getTitle ()+"-------------"+ vals. getAuthors ());
          30                }

          31        }
           catch (SQLException ex) {
          32            ex.printStackTrace();
          33        }
           finally {
          34            DbUtils.closeQuietly(conn);
          35        }

          36    }

          37}


               這兩種法輸出的結(jié)果應(yīng)該是一樣的。兩種處理方式都差不多,但我更愿意采用第一種,因?yàn)榈谝环N少寫一個(gè)bean,而且我測試過采用Map的方式即第一種方式性能要好的多,采用Bean性能比較低可能是因?yàn)椴捎梅瓷涞木壒剩捎梅瓷涞臇|東性能和不采用反射的還是有點(diǎn)差距。也是這個(gè)原因,不推薦采用 LazyDynaClass和LazyDynaBean,因?yàn)椴捎眠@二者是在運(yùn)行期動態(tài)創(chuàng)建Bean類和Bean屬性,然后再創(chuàng)建Bean對象的,其性能可想而知了(不過我沒有測試過啊,所以我說這個(gè)話可說是沒有根據(jù)的,感興趣的朋友自己測試一下,記得告訴我結(jié)果哦,呵呵),除了 MapListHandler以及BeanListHandler之外,DButils還提供了其他的Handler,如果這些不能滿足你的需求,你也可以自己實(shí)現(xiàn)一個(gè)Handler。
              最后,也是最大的體會,也許是最大的收獲吧,那就是:對于每一個(gè)項(xiàng)目,在根據(jù)每一個(gè)需求獲取相應(yīng)解決方案時(shí),先尋找開源組件,看是否已經(jīng)有滿足某些功能需求的開源組件,如果沒有,再考慮自主開發(fā)或者向第三方購買,否則盡量采用開源組件.
              請盡量享用開源的魅力,盡情的擁抱開源吧。
              好了,終于寫完了,有什么問題請聯(lián)系我,大家互相交流交流。

          posted on 2007-12-09 21:30 都市淘沙者 閱讀(793) 評論(1)  編輯  收藏 所屬分類: Hibernate/ORM

          評論

          # re: 利用Jakarta Commons組件beanutils、dbutils簡化JDBC數(shù)據(jù)庫操作(轉(zhuǎn)) 2008-11-28 16:48 網(wǎng)絡(luò)時(shí)空

          這篇文章寫得太好了!不過,要是將query傳遞多個(gè)參數(shù)的情況,也加進(jìn)去的話,就是一篇很好的文章了  回復(fù)  更多評論   

          主站蜘蛛池模板: 南昌县| 武山县| 河东区| 田林县| 连平县| 永丰县| 娱乐| 苍山县| 平乡县| 克东县| 正阳县| 清水县| 会泽县| 曲水县| 措美县| 从江县| 苍溪县| 潼关县| 蓝田县| 舞钢市| 阿尔山市| 龙南县| 无极县| 澎湖县| 恩平市| 建瓯市| 西吉县| 洞口县| 开化县| 图木舒克市| 巢湖市| 浪卡子县| 石城县| 巩留县| 茌平县| 江达县| 延长县| 陇南市| 灵丘县| 卫辉市| 商河县|