JDBC框架——DBUtils

JDBC框架——DBUtils



本文包括:

1、DBUtils簡介

2、DbUtils類

3、QueryRunner類

4、ResultSetHandler接口

5、使用步驟

1、DbUtils簡介

commons-dbutils 是 Apache 組織提供的一個開源

JDBC工具類庫,它是對JDBC的簡單封裝,學習成本極低,并且使用dbutils能極大簡化jdbc編碼的工作量,創建連接、結果集封裝、釋放資源,同時也不會影響程序的性能。創建連接、結果集封裝、釋放資源因此dbutils成為很多不喜歡hibernate的公司的首選。

API介紹:

org.apache.commons.dbutils.QueryRunner --- 核心

org.apache.commons.dbutils.ResultSetHandler --- 結果集封裝器

org.apache.commons.dbutils.DbUtils --- 工具類

地址:http://commons.apache.org/proper/commons-dbutils/

學習重點:多看看API,多看看官網的example!

2、DbUtils類

DbUtils :提供如加載驅動、關閉連接、事務提交、回滾等常規工作的工具類,里面的所有方法都是靜態的。主要方法如下:

DbUtils類提供了三個重載的關閉方法。這些方法檢查所提供的參數是不是NULL,如果不是的話,它們就關閉Connection、Statement和ResultSet。

publicstaticvoidclose(…) throws java.sql.SQLException

這一類"quietly"方法不僅能在Connection、Statement和ResultSet為NULL情況下避免關閉,還能隱藏一些在程序中拋出的SQLException。

publicstaticvoidcloseQuietly(…)

用來提交連接,然后關閉連接,并且在關閉連接時不拋出SQL異常。

publicstaticvoidcommitAndCloseQuietly(Connection conn)

裝載并注冊JDBC驅動程序,如果成功就返回true。使用該方法,你不需要捕捉這個異常ClassNotFoundException。

publicstaticbooleanloadDriver(java.lang.StringdriverClassName)

3、QueryRunner類

該類簡單化了SQL查詢,它與ResultSetHandler組合在一起使用可以完成大部分的數據庫操作,能夠大大減少編碼量。

QueryRunner類提供了兩個構造方法:

默認的構造方法:QueryRunner()

需要一個 javax.sql.DataSource 來作參數的構造方法:QueryRunner(DataSource ds)

注意:構造器需要傳入DataSource參數,所以必須要用到連接池,關于JDBC連接池可參考我之前的一篇文章:《JDBC進階——連接池》。在那篇文章中的JDBCUtils類中沒有相應的方法來獲得DataSource對象,所以應該在JDBCUtils類中加入如下代碼:

// 返回數據庫連接池publicstaticDataSourcegetDataSource(){returndataSource;}

常用方法(分為兩種情況):

批處理

batch(Connection conn,Stringsql,Object[][] params)// 傳遞連接批處理batch(Stringsql,Object[][] params)// 不傳遞連接批處理

查詢操作

publicObjectquery(Connection conn,Stringsql, ResultSetHandler rsh,Object... params)publicObjectquery(Stringsql, ResultSetHandler rsh,Object... params)

更新操作

public intupdate(Connectionconn,Stringsql, Object... params)publicintupdate(Stringsql, Object... params)

4、ResultSetHandler接口

該接口用于處理 java.sql.ResultSet,將數據按要求轉換為另一種形式。

ResultSetHandler 接口提供了一個單獨的方法:

Objecthandle(ResultSetrs){}

ResultSetHandler 接口的實現類(構造方法不唯一,在這里只用最常見的構造方法):

ArrayHandler():把結果集中的第一行數據轉成對象數組(存入Object[])。

ArrayListHandler():把結果集中的每一行數據都轉成一個對象數組,再存放到List中。

BeanHandler(Classtype):將結果集中的第一行數據封裝到一個對應的JavaBean實例中。

BeanListHandler(Classtype):將結果集中的每一行數據都封裝到一個對應的JavaBean實例中,存放到List里。

Parameters:

type - The Class that objects returned from handle() are created from.

ColumnListHandler(String columnName/int columnIndex):將結果集中某一列的數據存放到List中。

MapHandler():將結果集中的第一行數據封裝到一個Map里,key是列名,value就是對應的值。

MapListHandler():將結果集中的每一行數據都封裝到一個Map里,然后再將所有的Map存放到List中。

KeyedHandler(String columnName):將結果集每一行數據保存到一個“小”map中,key為列名,value該列的值,再將所有“小”map對象保存到一個“大”map中 , “大”map中的key為指定列,value為“小”map對象

ScalarHandler(int columnIndex):通常用來保存只有一行一列的結果集。

注意:DBUtils-1.4版本中的 ScalarHandler, ColumnHandler, and KeyedHandler沒有泛型!要使用1.5以上的版本。

Release Notes Address :http://commons.apache.org/proper/commons-dbutils/changes-report.html

5、使用步驟

將DBUtils的jar包加入到項目工程的build path中。

對于CUD,有兩種不同的情況:

情況一:

如果使用 QueryRunner(DataSource ds) 構造器創建QueryRunner對象,需要使用連接池,如DBCP、C3P0等等,數據庫事務交給DBUtils框架進行管理 ----默認情況下每條SQL語句單獨一個事務

在這種情況下,使用如下方法:

batch(Stringsql, Object[][]params)? query(Stringsql, ResultSetHandlerrsh, Object...params)? update(Stringsql, Object...params)

demo:

@TestpublicvoidtestDelete()throwsSQLException{? ? ? QueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());? ? ? String sql ="delete from users where id = ?";? ? ? queryRunner.update(sql,3);? }@TestpublicvoidtestUpdate()throwsSQLException{? ? ? QueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());? ? ? String sql ="update users set password = ? where username = ?";? ? ? Object[] param = {"nihao","小明"};? ? ? queryRunner.update(sql, param);? }@TestpublicvoidtestInsert()throwsSQLException{// 第一步 創建QueryRunner對象QueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());// 第二步 準備方法參數String sql ="insert into users values(null,?,?,?)";? ? ? Object[] param = {"小麗","qwe","xiaoli@itcast.cn"};// 第三步 調用 query / updatequeryRunner.update(sql, param);? }

情況二:

如果使用 QueryRunner() 構造器創建QueryRunner對象 ,需要自己管理事務,因為框架沒有連接池無法獲得數據庫連接。

在這種情況下,要使用傳入Connection對象參數的方法:

query(Connection conn,Stringsql, ResultSetHandler rsh, Object...params)? update(Connection conn,Stringsql, Object...params)

demo:

// 事務控制@TestpublicvoidtestTransfer()throwsSQLException {doublemoney =100;StringoutAccount ="aaa";StringinAccount ="bbb";Stringsql1 ="update account set money = money - ? where name= ?";Stringsql2 ="update account set money = money + ? where name= ?";// 傳入DataSource的構造器,默認每條SQL語句一個單獨事務,而在這里要自己管理業務,所以不合適!// QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());QueryRunner queryRunner =newQueryRunner();// 不要傳遞連接池 --- 手動事務管理Connection conn = JDBCUtils.getConnection();? ? ? conn.setAutoCommit(false);try{? ? ? ? ? queryRunner.update(conn, sql1, money, outAccount);// 注意要傳入Connection對象的方法// int d = 1 / 0;queryRunner.update(conn, sql2, money, inAccount);? ? ? ? ? System.out.println("事務提交!");? ? ? ? ? DbUtils.commitAndCloseQuietly(conn);? ? ? }catch(Exception e) {? ? ? ? ? System.out.println("事務回滾!");? ? ? ? ? DbUtils.rollbackAndCloseQuietly(conn);? ? ? ? ? e.printStackTrace();? ? ? }? }

對于R,需要用到ResultSetHandler接口,該接口有9大實現類,

publicclass ResultSetHandlerTest {// ScalarHandler 通常用于保存只有一行一列的結果集,例如分組函數@Testpublicvoiddemo9()throwsSQLException {? ? ? ? QueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());Stringsql ="select count(*) from account";longcount = (Long) queryRunner.query(sql,newScalarHandler(1));// 得到結果集的第1列System.out.println(count);? ? }// KeyedHandler 將結果集每一行數據保存到一個“小”map中,key為列名,value該列的值,再將所有“小”map對象保存到一個“大”map中 , “大”map中的key為指定列,value為“小”map對象@Testpublicvoiddemo8()throwsSQLException {? ? ? ? QueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());Stringsql ="select * from account";? ? ? ? Map>map= queryRunner.query(sql,newKeyedHandler("id"));? ? ? ? System.out.println(map);? ? }// MapListHandler 將結果集每一行數據保存到map中,key列名 value該列的值 ---- 再將所有map對象保存到List集合中@Testpublicvoiddemo7()throwsSQLException {? ? ? ? QueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());Stringsql ="select * from account";? ? ? ? List> list = queryRunner.query(sql,newMapListHandler());for(Mapmap: list) {? ? ? ? ? ? System.out.println(map);? ? ? ? }? ? }// MapHander 將結果集第一行數據封裝到Map集合中,key是列名,value為該列的值@Testpublicvoiddemo6()throwsSQLException {? ? ? ? QueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());Stringsql ="select * from account";? ? ? ? Mapmap= queryRunner.query(sql,newMapHandler());// 列名為String類型,該列的值為Object類型System.out.println(map);? ? }// ColumnListHandler 獲得結果集的某一列,將該列的所有值存入List中@Testpublicvoiddemo5()throwsSQLException {? ? ? ? QueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());Stringsql ="select * from account";// 因為每列類型都不一樣,所以用List存儲// List list = queryRunner.query(sql,// new ColumnListHandler("name")); // 得到表列名為name的列List list = queryRunner.query(sql,newColumnListHandler(2));// 得到結果集的第2列System.out.println(list);? ? }// BeanListHander 將結果集每一條數據,轉為JavaBean對象,再保存到list集合中@Testpublicvoiddemo4()throwsSQLException {? ? ? ? QueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());Stringsql ="select * from account";? ? ? ? List accounts = queryRunner.query(sql,newBeanListHandler(Account.class));for(Account account : accounts) {? ? ? ? ? ? System.out.println(account.getId());? ? ? ? ? ? System.out.println(account.getName());? ? ? ? ? ? System.out.println(account.getMoney());? ? ? ? ? ? System.out.println("----------------");? ? ? ? }? ? }// BeanHandler 將結果集第一行數據封裝到JavaBean對象中@Testpublicvoiddemo3()throwsSQLException {? ? ? ? QueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());Stringsql ="select * from account";// 傳入 Account.class字節碼文件:為了在方法中 通過反射構造Account對象// 使用BeanHandler注意事項 :數據庫中的表列名 與 Bean類中屬性 名稱一致!!!Account account = queryRunner.query(sql,newBeanHandler(? ? ? ? ? ? ? ? Account.class));? ? ? ? System.out.println(account.getId());? ? ? ? System.out.println(account.getName());? ? ? ? System.out.println(account.getMoney());? ? }// ArrayListHandler 將結果集每一行數據保存到List中@Testpublicvoiddemo2()throwsSQLException {? ? ? ? QueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());Stringsql ="select * from account";? ? ? ? List list = queryRunner.query(sql,newArrayListHandler());for(Object[] objects : list) {? ? ? ? ? ? System.out.println(Arrays.toString(objects));? ? ? ? }? ? }// ArrayHandler 將結果集第一行數據保存到Object[]中@Testpublicvoiddemo1()throwsSQLException {// 使用DBUtilsQueryRunner queryRunner =newQueryRunner(JDBCUtils.getDataSource());Stringsql ="select * from account";// 對象數組存儲rs第一行數據的所有列Object[] values = queryRunner.query(sql,newArrayHandler());? ? ? ? System.out.println(Arrays.toString(values));? ? } }

JDBC文集:

Java 與數據庫的橋梁——JDBC:http://www.lxweimin.com/p/c0acbd18794c

JDBC 進階——連接池:http://www.lxweimin.com/p/ad0ff2961597

JDBC 進階——元數據:http://www.lxweimin.com/p/36d5d76342f1

JDBC框架——DBUtils:http://www.lxweimin.com/p/10241754cdd7

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容