首頁 資料庫 mysql教程 利用Jakarta Commons组件beanutils、dbutils简化JDBC数据库操作

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

Jun 07, 2016 pm 02:59 PM
commons 使用 組件

虽然现在出现了很多ORM框架,可是还是有很多朋友也许还在使用JDBC,就像我现在一样,除了学习的时候在使用Hibernate、Spring类似这些优秀的框架,工作时一直都在使用JDBC。本文就简单介绍一下利用Jakarta Commons旗下beanutils、dbutils简化JDBC数据库操作,

  虽然现在出现了很多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,脚本如下:

CREATE TABLE book(

  id int(11) NOT NULL auto_increment,

  title varchar(50) character set latin1 NOT NULL,

  authors varchar(50) character set latin1 default NULL,

  PRIMARY KEY  (id)

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

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

package cn.qtone.test;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.Statement;

import java.util.Iterator;

import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.ResultSetDynaClass;
public class BeanutilsJDBCTest{
       public static void main(String[] args) {
              Connection con = null;
              Statement st = null;
              ResultSet rs = null;
              try {
                     Class.forName("com.mysql.jdbc.Driver");
                     String url = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";
                     con = DriverManager.getConnection(url, "root", "hyys");

                     st = con.createStatement();
                     rs = st.executeQuery("select * from book");

                     ResultSetDynaClass rsDynaClass = new ResultSetDynaClass(rs);

                     Iterator itr = rsDynaClass.iterator();

                     System.out.println("title-------------authors");

                     while (itr.hasNext()) {


                            DynaBean dBean = (DynaBean) itr.next();

                            System.out.println(PropertyUtils.getSimpleProperty(dBean,"title")

                                          + "-------------"+ PropertyUtils.getSimpleProperty(dBean, "authors"));

                     }

              } catch (Exception e) {
                     e.printStackTrace();

              } finally {


                     try {

                            if (rs != null) {

                                   rs.close();

                            }

                            if (st != null) {

                                   st.close();

                            }
                            if (con != null) {

                                   con.close();

                            }
                     } catch (Exception e) {

                            e.printStackTrace();

                     }

              }
       }

}


用RowSetDynaClass处理的源代码如下所示:


package cn.qtone.test;


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import java.util.Iterator;
import java.util.List;
import org.apache.commons.beanutils.DynaBean;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.beanutils.RowSetDynaClass;

public class BeanutilsJDBCTest{
       public static void main(String[] args) {
              List rsDynaClass = rsTest();
              System.out.println("title ------------- authors ");
              Iterator itr = rsDynaClass.iterator();

              while (itr.hasNext()) {

                     DynaBean dBean = (DynaBean) itr.next();

                     try {
                            System.out.println(PropertyUtils.getSimpleProperty(dBean,"name")

                                          + "-------------"+ PropertyUtils.getSimpleProperty(dBean, "mobile"));


                     } catch (Exception e) {

                            // TODO 自动生成 catch 块

                            e.printStackTrace();

                     }
              }

       }
       private static List rsTest() {

              Connection con = null;

              Statement st = null;

              ResultSet rs = null;

              try {

                     Class.forName("com.mysql.jdbc.Driver");

                     String url = "jdbc:mysql://127.0.0.1:3306/publish?useUnicode=true&characterEncoding=GBK";

                     con = DriverManager.getConnection(url, "root", "hyys");

                     st = con.createStatement();

                     rs = st.executeQuery("select * from book");

                     RowSetDynaClass rsdc = new RowSetDynaClass(rs);
                     return rsdc.getRows();


              } catch (Exception e) {
                     e.printStackTrace();
              } finally {

                     try {
                            if (rs != null) {
                                   rs.close();


                            }

                            if (st != null) {

                                   st.close();

                            }

                            if (con != null) {
                                   con.close();
                            }
                     } catch (Exception e) {

                            e.printStackTrace();

                     }

              }


              return null;

       }

}


这两个方法输出的结果应该是一样的。但是很显然第二种方式比第一种方式要好,它把数据访问部分抽取出来放到一个方法中,显得简单清晰。

其实在利用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,示例代码如下所示:
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                         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             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。
    最后,也是最大的体会,也许是最大的收获吧,那就是:对于每一个项目,在根据每一个需求获取相应解决方案时,先寻找开源组件,看是否已经有满足某些功能需求的开源组件,如果没有,再考虑自主开发或者向第三方购买,否则尽量采用开源组件.
    请尽量享用开源的魅力,尽情的拥抱开源吧。
    好了,终于写完了,有什么问题请联系我,大家互相交流交流

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

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1322
25
PHP教程
1270
29
C# 教程
1250
24
如何安裝Win10舊版元件DirectPlay 如何安裝Win10舊版元件DirectPlay Dec 28, 2023 pm 03:43 PM

不少用戶在玩win10的的一些遊戲的時候總是會遇到一些問題,比如說卡屏和花屏等等情況,這個時候我們是可以採用打開directplay這個功能來解決的,而且功能的操作方法也很簡單。 win10舊版元件directplay怎麼安裝1、在搜尋框裡面輸入「控制台」然後開啟2、檢視方式選擇大圖示3、找到「程式與功能」4、點選左側的啟用或關閉win功能5、選擇舊版這裡的勾選上就可以了

如何利用GitLab進行專案文件管理 如何利用GitLab進行專案文件管理 Oct 20, 2023 am 10:40 AM

如何利用GitLab進行專案文件管理一、背景介紹在軟體開發過程中,專案文件是非常重要的資料,不僅能夠幫助開發團隊了解專案的需求和設計,還能提供給測試團隊和客戶參考。為了方便專案文件的版本控制和團隊協作,我們可以利用GitLab來進行專案文件管理。 GitLab是一個基於Git的版本控制系統,除了支援程式碼管理,還可以管理專案文件。二、GitLab環境建置首先,我

如何使用 Vue 實現日曆元件? 如何使用 Vue 實現日曆元件? Jun 25, 2023 pm 01:28 PM

Vue是一款非常流行的前端框架,它提供了許多工具和功能,如元件化、資料綁定、事件處理等,能夠幫助開發者建立出高效、靈活和易於維護的Web應用程式。在這篇文章中,我來介紹如何使用Vue實作一個日曆元件。 1.需求分析首先,我們需要分析這個行事曆組件的需求。一個基本的日曆應該具備以下功能:展示當前月份的日曆頁面;支援切換到前一月或下一月;支援點擊某一天,

VUE3開發基礎:使用extends繼承元件 VUE3開發基礎:使用extends繼承元件 Jun 16, 2023 am 08:58 AM

Vue是目前最受歡迎的前端框架之一,而VUE3則是Vue框架的最新版本,相較於VUE2,VUE3具備了更高的性能和更出色的開發體驗,成為了眾多開發者的首選。在VUE3中,使用extends繼承元件是一個非常實用的開發方式,本文將為大家介紹如何使用extends繼承元件。 extends是什麼?在Vue中,extends是一個非常實用的屬性,它可以用於子元件繼承父

如何開啟win10舊版組件的設置 如何開啟win10舊版組件的設置 Dec 22, 2023 am 08:45 AM

win10舊版元件是需要使用者自己去設定裡面打開的,因為很多的元件平時都是預設關閉的狀態,首先我們需要進入到設定裡面,操作很簡單,跟著下面的步驟來就可以了win10舊版元件在哪裡開啟1、點選開始,然後點選「win系統」2、點選進入控制台3、再點選下面的程式4、點選「啟用或關閉win功能」5、在這裡就可以選擇你要的開啟了

Angular元件及其顯示屬性:了解非block預設值 Angular元件及其顯示屬性:了解非block預設值 Mar 15, 2024 pm 04:51 PM

Angular框架中元件的預設顯示行為不是區塊級元素。這種設計選擇促進了元件樣式的封裝,並鼓勵開發人員有意識地定義每個元件的顯示方式。透過明確設定CSS屬性 display,Angular組件的顯示可以完全控制,從而實現所需的佈局和響應能力。

聊聊Vue怎麼透過JSX動態渲染元件 聊聊Vue怎麼透過JSX動態渲染元件 Dec 05, 2022 pm 06:52 PM

Vue怎麼透過JSX動態渲染元件?以下這篇文章跟大家介紹Vue高效率透過JSX動態渲染元件的方法,希望對大家有幫助!

VSCode插件分享:一個即時預覽Vue/React元件的插件 VSCode插件分享:一個即時預覽Vue/React元件的插件 Mar 17, 2022 pm 08:07 PM

在VSCode中開發Vue/React元件時,怎麼即時預覽元件?本篇文章就跟大家分享一個VSCode 中即時預​​覽Vue/React元件的插件,希望對大家有幫助!

See all articles