開源JDBC工具類DbUtils


  本篇將會詳細地介紹Apache公司的JDBC幫助工具類DbUtils以及如何使用。在上一篇中我們已經通過將以前對dao層使用JDBC操作數據庫的冗余代碼進行了簡易封裝形成自己的簡單工具類JdbcUtils,而在這過程中很多都是借鑒和參考了DbUtils的代碼,因此通過上一篇的學習,會讓我們在對DbUtils進行更快速簡單的認識。

  俗話說學習一個開源的工具最好的方法就是看其官方文檔,是的,在Apache官網中對DbUtils進行了詳細的介紹:http://commons.apache.org/proper/commons-dbutils/ 。(或者下載了DbUtils的jar中也有相應文檔)

  DbUtils是一些類組成的用於簡化JDBC開發的庫,解決我們以前根據“模板”代碼寫出的大部分的冗余部分,將我們的代碼進行最大程度的簡化,使我們只關心於查詢更新(包括添加、修改和刪除)數據。就好像上一篇博客中我們重點寫的query和update方法。

  DbUtils能做些什么?雖然JDBC代碼不難,但是根據我們以前所寫的“模板”代碼費時又費力,非常容易丟失鏈接並且難以追尋,而使用DbUtils基本不會發生資源泄露(比如鏈接的丟失)。當然和上一篇博文相同,DbUtils也提供了一個對結果集處理的接口ResultSetHandler,我們可以實現這個接口來對結果集進行處理,也可以使用DbUtils提供的實現類,例如BeanHandler或者BeanListHandler等等,有很多實用的結果集處理器類。如果有一些公司不使用hibernate的話一般會選用DbUtils。

  DbUtils最主要的就兩個,QueryRunner類和ResultSetHandler接口。

  QueryRunner類這個類主要用於提供各種重載形式的batch方法、query方法和update 方法,其中update 方法包含添加、刪除和修改。

  QueryRunner並不算一個靜態工具類,因此我們要使用必須先創建一個QueryRunner類的對象,而這就有兩種構造器,分別是無參的和有參的,其中有參的構造器接收一個連接池對象DataSource。

  

  

  可以從手冊中看到,如果在創建QueryRunner對象時給定了一個連接池對象,那么在一些不需要Connection對象為參數的方法被調用時會從連接池中自動獲取連接,調用完后會將連接重新返回到連接池中;而對於無參的構造器來說,在調用方法時必須指定Connection對象,同時調用完方法后Connection對象的處理要自己負責。

  下面就看看對於無參和有參的QueryRunner對象的各種重載形式的query方法和update方法:

  

  

  可以看到這些方法中主要就分為兩種,一種是有Connection對象參數的,一種是無Connection對象參數的。上面已經說過了,無Connection對象參數的方法是從有參QueryRunner的連接池中獲取鏈接,同時會自動將連接返還給連接池。而有Connection參數的方法由調用者負責關閉連接,這種方法看似麻煩,但是由多條SQL組成的事務進行整體執行卻是必須的,因為我們不需要只執行一條SQL就還給連接池。

  除了query方法和update方法,QueryRunner類還有一個batch方法,用於執行SQL批處理:

  

  這個方法用於對某一條SQL執行多次,而我們提供給這個方法的參數中是一個二維數組,那么怎么用呢?

  比如“insert into user(id,name,age) values(?,?,?)”這樣的SQL語句,batch方法中的二維數組參數就可以是 [ [1,”Ding”,25],[2,”LRR”,24] ] 這樣的形式,也就是批處理執行兩次,而每次的參數都不同。

  上面的介紹基本就是QueryRunner的全部,當然QueryRunner只是DbUtils的一部分,而另一部分在於QueryRunner中query方法參數中的ResultSetHandler接口,用於處理結果集,這一點上一篇博客已經講述的很清楚了。而在DbUtils中為我們已經寫好了更多的這個接口的實現類:

  

  除了我們上一篇博客自己動手實現的BeanHandler和BeanListHandler之外,在DbUtils中可以使用便捷的結果集處理器還有

  ArrayHandler:把結果集中的第一行數據封裝進對象數組中。

  ArrayListHandler:把結果集中的每一行數據封裝進數組,再將這些數組存進List集合中。

  ColumnListHandler:將結果集中的某一所有的數據存進List集合中。

  KeyedHandler:將結果集中的每一行數據封裝進一個Map中,再把這些Map存到一個Map里,其Key為指定的Key。

  MapHandler:將結果集中的第一行數據封裝進Map里,Key為列名,value就是對應的值。

  MapListHandler:將結果集中的每一行數據封裝到Map中,再將這些Map存放進List中。

 

  記得上一篇博客中我們在JDBC工具類JdbcUtils中重點創建的自定義的update方法和query方法嗎(上一篇博客的第四點和第五點),那只是為了我們將冗余代碼進行封裝,而在本篇中我們可以在JdbcUtils中刪了這里兩個方法,而直接在dao層中使用DbUtils進行低層的增刪改查。

例1

  那么在下面的代碼中就對上一篇博客最后的UserDao中的增刪改查進行重構:

 1 public class UserDao {  2     // 添加用戶
 3     public void add(User user) throws SQLException {  4         QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());  5         String sql = "insert into user(id,name,age) values(?,?,?)";  6         Object[] params = { user.getId(), user.getName(), user.getAge() };  7  qr.update(sql, params);  8  }  9 
10     // 刪除用戶
11     public void delete(int id) throws SQLException { 12         QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource()); 13         String sql = "delete from user where id=?"; 14         Object params = id; 15  qr.update(sql, params); 16  } 17 
18     // 修改用戶
19     public void update(User user) throws SQLException { 20         QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource()); 21         String sql = "update user set name=?,age=? where id=?"; 22         Object[] params = { user.getName(), user.getAge(), user.getId() }; 23  qr.update(sql, params); 24  } 25 
26     // 查找某個用戶
27     public User find(int id) throws SQLException { 28         QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource()); 29         String sql = "select * from user where id=?"; 30         Object params = id; 31         User user = qr.query(sql, new BeanHandler<>(User.class), params); 32         return user; 33  } 34 
35     // 列出所有用戶
36     public List<User> getAllUser() throws SQLException { 37         QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource()); 38         String sql = "select * from user"; 39         List<User> list = qr.query(sql, new BeanListHandler<>(User.class)); 40         return list; 41  } 42 }
View Code

  可以看到使用QueryRunner就將我們的增刪改查語句變得非常簡單,同時我們在工具類JdbcUtils中也不用另外再寫update方法和query方法,在JdbcUtils中主要是創建連接池。由於我們在創建QueryRunner對象時使用了DataSource作為參數,這樣我們在使用無Connection對象的update方法和query方法都可以不用指定連接,同時這些方法會將我們的連接自動放回連接池,因此我們在JdbcUtils甚至都可以不用寫釋放資源的代碼(當然具體情況具體分析)。 

例2

  再補充一個使用DbUtils的批處理batch方法的demo:

public void batchInsertTest() throws SQLException { QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource()); String sql = "insert into user(id,name,age) values(?,?,?)"; Object[][] params = new Object[5][3]; for(int i=0;i<params.length;i++) { params[i] = new Object[]{i+1,"aa"+i,25+i}; } qr.batch(sql, params); }
View Code

結果如下:

 

  關於DbUtils中的QueryRunner類就差不多介紹完了,主要就是batch、query和update 方法。

  而對於結果集處理器類,DbUtils給我們提供了很多針對ResultSetHandler接口的實現類,如果這些實現類都不能滿足我們的需要,我們也可以實現ResultSetHandler接口來制作我們所需要功能的實現類。

例3

  下面使用DbUtils中的結果集處理器類之一的ArrayHandler類來簡單演示下demo(以上面批處理batch方法調用后的數據庫中數據為例):

1 public void arrayHandlerTest() throws SQLException { 2         QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource()); 3         String sql = "select * from user"; 4         Object[] firstUser = qr.query(sql, new ArrayHandler()); 5         for(Object o:firstUser) { 6  System.out.println(o); 7  } 8     }
View Code

  ArrayHandler類只將結果集的第一行數據封裝進一個對象數組中,在控制台觀察:

  

例4:

  有時候我們需要計算一張表中的總記錄數,例如在使用數據庫進行分頁的時候就需要知道有多少數據,那么將查詢結果以結果集返回也可以使用ArrayHandler簡單處理,因為數組的第一個元素就是查詢結果,但下面的代碼看似沒有問題,卻在運行時會拋出異常:

1 public void countTest() throws SQLException { 2         QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource()); 3         String sql = "select count(*) from user"; 4         Object[] result = qr.query(sql, new ArrayHandler()); 5         int count = (int) result[0]; 6  System.out.println(count); 7     }
View Code

異常原因:

  

  也就是說在MySQL中以count方法在JDBC中是以Long類型返回查詢的數值,因此我們不能只用Integer類型。這點要注意,但是總記錄數不大時可以將Long類型強制轉換為Integer類型:

1 public void countTest() throws SQLException { 2         QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource()); 3         String sql = "select count(*) from user"; 4         Object[] result = qr.query(sql, new ArrayHandler()); 5         int count = ((Long)result[0]).intValue(); 6  System.out.println(count); 7 }
View Code

  當然還有其他的很實用的結果集處理器類,這里就不一一介紹了。本篇對DbUtils的講解就結束了,對於DbUtils的使用是很簡單的,只要掌握了QueryRunner類和ResultSetHandler接口及其實現類,就能很好的掌握DbUtils。

 

 

          

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM