Dict.CN 在线词典, 英语学习, 在线翻译

都市淘沙者

荔枝FM Everyone can be host

统计

留言簿(23)

积分与排名

优秀学习网站

友情连接

阅读排行榜

评论排行榜

利用Jakarta Commons组件beanutils、dbutils简化JDBC数据库操作(转)

关键字:beanutils、dbutils、JDBC 数据库
摘要:本文简单介绍了Jakarta Commons旗下beanutils、dbutils在基于JDBC API数据库存取操作中的运用。
    虽然现在出现了很多ORM框架,可是还是有很多朋友也许还在使用JDBC,就像我现在一样,除了学习的时候在使用Hibernate、Spring类似这些优秀的框架,工作时一直都在使用JDBC。本文就简单介绍一下利用Jakarta Commons旗下beanutils、dbutils简化JDBC 数据库操作,以抛砖引玉,希望对像我一样在使用JDBC的朋友有所帮助。
    下面就分两部分简单介绍beanutils、dbutils在基于JDBC API数据库存取操作中的运用。第一部分显介绍beanutils在JDBC数据库存取操作中的运用,第二部分介绍dbutils在JDBC 数据库存取操作中的运用,最后看看他们的优缺点,谈谈本人在项目运用过程中对他们的一点心得体会,仅供参考,其中有错误的地方希望大虾不吝赐教,大家多多交流共同进步。
一、Jakarta Commons beanutils
    Beanutils是操作Bean的锐利武器,其提过的 BeanUtils工具类可以简单方便的读取或设置Bean的属性,利用Dyna系列,还可以在运行期创建Bean,符合懒人的习惯,正如 LazyDynaBean,LazyDynaClass一样,呵呵。这些用法已经有很多文章提及,也可以参考apache的官方文档。
    对于直接利用JDBC API访问数据库时(这里针对的是返回结果集ResultSet的查询select),大多数都是采用两种方式,一种是取出返回的结果集的数据存于Map中,另一种方式是Bean里。针对第二种方式,Beanutils里提供了ResultSetDynaClass结合 DynaBean以及RowSetDynaClass结合DynaBean来简化操作。下面用以个简单的例子展示一下beanutils的这两个类在 JDBC数据库操作中的运用。
    请在本机建立数据库publish,我用的是MySQL,在publish数据库中建立表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


     然后用你喜欢的编辑器建立一个类BeanutilsJDBCTest,我们先用ResultSetDynaClass来处理,然后再用 RowSetDynaClass来实现同样的类,之后看看他们之间有什么不同,用ResultSetDynaClass处理的源代码如下所示:
     然后用你喜欢的编辑器建立一个类BeanutilsJDBCTest,我们先用ResultSetDynaClass来处理,然后再用 RowSetDynaClass来实现同样的类,之后看看他们之间有什么不同,用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}
 



     这两个方法输出的结果应该是一样的。但是很显然第二种方式比第一种方式要好,它把数据访问部分抽取出来放到一个方法中,显得简单清晰。
      其实在利用ResultSetDynaClass时,必须在ResultSet等数据库资源关闭之前,处理好那些数据,你不能在资源关闭之后使用 DynaBean,否则就会抛出异常,异常就是说不能在ResultSet之后存取数据(具体的异常名我也忘了),当然你也可以采用以前的方式一个一个的把数据放到Map里,如果你一定要那样做,建议还是别用Beanutils,因为这没带给你什么好处。总之利用ResultSetDynaClass你的程序的扩展性非常部好。
    从第二中方式可以看出,利用RowSetDynaClass可以很好的解决上述 ResultSetDynaClass遇到的问题,RowSetDynaClass的getRows()方法,把每一行封装在一个DynaBean对象里,然后,把说有的行放到一个List里,之后你就可以对返回的List里的每一个DynaBean进行处理,此外对于DynaBean你还可以采用标准的get/set方式处理,当然你也可以用PropertyUtils. getSimpleProperty(Object bean,  String name)进行处理。
    从上面的分析中,你应该可以决定你应该使用ResultSetDynaClass还是RowSetDynaClass了。

二、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,示例代码如下所示:

 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的方式代替进行处理
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令人难缠的是关闭那些资源以及处理那些异常,而这里采用Dbutils显然代码量减少了很多。
上例在处理结果集时,它把数据库中的每一行映射成一个Map,其中列名作为Key,该列对应的值作为Value存放,查询的所有的数据一起放在一个List里,然后进行处理,当然,一个更明智的处理是直接返回List然后再单独进行处理。
事实上上例返回的结果集中的每一行不必放在一个Map里,你可以放在一个Bean里,当然如果你真的很懒,你也可以使用Beanutils的LazyDynaClass和LazyDynaBean,不过也许没有必要那么做,至于原因请看下文。

如果使用Bean而不是用Map,那么,你也许需要建立一个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的方式代替进行处理
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}


     这两种法输出的结果应该是一样的。两种处理方式都差不多,但我更愿意采用第一种,因为第一种少写一个bean,而且我测试过采用Map的方式即第一种方式性能要好的多,采用Bean性能比较低可能是因为采用反射的缘故,采用反射的东东性能和不采用反射的还是有点差距。也是这个原因,不推荐采用 LazyDynaClass和LazyDynaBean,因为采用这二者是在运行期动态创建Bean类和Bean属性,然后再创建Bean对象的,其性能可想而知了(不过我没有测试过啊,所以我说这个话可说是没有根据的,感兴趣的朋友自己测试一下,记得告诉我结果哦,呵呵),除了 MapListHandler以及BeanListHandler之外,DButils还提供了其他的Handler,如果这些不能满足你的需求,你也可以自己实现一个Handler。
    最后,也是最大的体会,也许是最大的收获吧,那就是:对于每一个项目,在根据每一个需求获取相应解决方案时,先寻找开源组件,看是否已经有满足某些功能需求的开源组件,如果没有,再考虑自主开发或者向第三方购买,否则尽量采用开源组件.
    请尽量享用开源的魅力,尽情的拥抱开源吧。
    好了,终于写完了,有什么问题请联系我,大家互相交流交流。

posted on 2007-12-09 21:30 都市淘沙者 阅读(784) 评论(1)  编辑  收藏 所属分类: Hibernate/ORM

评论

# re: 利用Jakarta Commons组件beanutils、dbutils简化JDBC数据库操作(转) 2008-11-28 16:48 网络时空

这篇文章写得太好了!不过,要是将query传递多个参数的情况,也加进去的话,就是一篇很好的文章了  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: