Commons DBUtils類庫是小型的設計於易於使用JDBC的類集合。JDBC資源清理是平凡的,容易出錯,以致於這些類從你的代碼中抽象出清理代碼,剩下你最初真正想要使用JDBC作的代碼:查詢和更新數據。html
使用DBUtils的一些優點:java
沒有資源泄露的可能性。正確的JDBC編碼並不難,但它耗時且乏味。這經常會致使鏈接泄漏可能很難追蹤。sql
清晰的持久化代碼。須要持久化數據到數據庫中的代碼大幅減小。剩下的代碼清晰的表達你的意圖沒有凌亂的資源清理。數據庫
從ResultSet自動填充JavaBean。你不須要經過setter方法手動複製列值到bean實例。ResultSet的每行表明一個徹底填充的bean實例。apache
DBUtils設計爲:c#
小巧——你應該可以在很短的時間理解整個包。api
透明——DbUtils不在背後作任何魔術。你指定給它一個查詢,它執行查詢併爲你清理。數組
快速——你不須要建立一百萬個臨時對象使用DbUtils。框架
DbUtils不是:異步
一個對象/關係橋——有不少好的O/R工具。DbUtils是爲想要使用JDBC開發人員設計。
一個數據訪問對象(DAO)框架——DbUtils能用於構建一個DAO框架。
面向對象的通用數據庫對象的抽象,像Table、Column或PrimaryKey。
任意種類的重量級框架——目標是一個簡單的和易於使用的JDBC輔助庫。
DbUtils是很是小的類庫,所以它不須要花很長時間去遍歷每一個類的APIs。DbUtils的核心類或接口是QueryRunner和ResultSetHandler。你不須要知道關於每一個其它的DbUtils類。如下例子演示如何使用這些類。
// 建立一個ResultSetHandler實現轉換第一行爲一個Object[] ResultSetHandler<Object[]> h = new ResultSetHandler<Object[]>() { public Object[] handle(ResultSet rs) throws SQLException { if (!rs.next()) { return null; } ResultSetMetaData meta = rs.getMetaData(); int cols = meta.getColumnCount(); Object[] result = new Object[cols]; for (int i = 0; i < cols; i++) { result[i] = rs.getObject(i + 1); } return result; } }; // 建立一個QueryRunner將使用指定DataSource的鏈接 QueryRunner run = new QueryRunner(dataSource); // 執行查詢並獲取處理器返回的結果 Object[] result = run.query("SELECT * FROM Person WHERE name=?", h, "John Doe");
你也能使用java.sql.Connection對象執行前面的查詢而不是一個DataSource。注意,你負責關閉Connection。
ResultSetHandler<Object[]> h = ... // 和上面同樣定義一個處理器 // 沒有DataSource,所以咱們必須手動處理鏈接QueryRunner run = new QueryRunner(); Connection conn = ... // 打開一個鏈接 try{ Object[] result = run.query( conn, "SELECT * FROM Person WHERE name=?", h, "John Doe"); // 使用結果 } finally { // 使用該輔助方法,所以咱們不須要檢查null DbUtils.close(conn); }
你不只能從數據庫抓取數據——你也能插入或更新數據。如下示例將首先插入一條person記錄到數據庫而後改變person的身高。
QueryRunner run = new QueryRunner( dataSource ); try { // 執行SQL更新語句並返回咱們插入的數量 int inserts = run.update( "INSERT INTO Person (name,height) VALUES (?,?)", "John Doe", 1.82 ); // 使用可變參數和自動裝箱來簡化代碼 int updates = run.update( "UPDATE Person SET height=? WHERE name=?", 2.05, "John Doe" ); } catch(SQLException sqle) { // 處理它 }
對於長時間運行調用你能使用AsyncQueryRunner執行異步調用。AsyncQueryRunner類有與QueryRunner相同的方法;然而,方法返回一個Future。
ExecutorService service = Executors.newCachedThreadPool(); AsyncQueryRunner asyncRun = new AsyncQueryRunner(service); Connection conn = … try { // 建立一個更新調用的Callable Future<Integer> = asyncRun.update(conn, "UPDATE Person SET height=? WHERE name=?", 2.05, "John Doe" ); // 執行 f.get(); } catch(SQLException sqle) { // 處理異常 }
在上面的例子中,咱們實現ResultSetHandler接口把ResultSet的第一行轉換爲Object[]。這是一個至關通用能夠跨多個項目重用的實現。DbUtils意識到了這一點,在org.apache.commons.dbutils.handlers包中提供一組ResultSetHandler實現執行常見的轉換爲數組、Map和JavaBeans。每一個實現有一個版本只轉換ResultSet中的第一行和其它轉換ResultSet中的全部行。
咱們將開始一個例子,使用BeanHandler從ResultSet中抓取每一行,並轉換到JavaBean中。
QueryRunner run = new QueryRunner(dataSource); // 使用BeanHandler實現轉換ResultSet的第一行爲一個Person JavaBean ResultSetHandler<Person> h = new BeanHandler<Person>(Person.class); // 使用一個佔位符參數執行SQL語句並返回BeanHandler產生的新Person對象的結果 Person p = run.query("SELECT * FROM Person WHERE name=?", h, "John Doe");
此時,咱們將使用BeanListHandler從ResultSet抓取全部行並轉換它們到一個JavaBeans的List中。
QueryRunner run = new QueryRunner(dataSource); // 使用BeanListHandler實現轉換ResultSet的全部行到Person JavaBeans的List中 ResultSetHandler<List<Person>> h = new BeanListHandler<Person>(Person.class); // 執行SQL語句並返回BeanListHandler產生的Person對象的List結果 List<Person> persons = run.query("SELECT * FROM Person", h);
每一個提供的ResultSetHandler實現接收一個RowProcessor作實際的行到對象的轉換。默認處理器使用BasicRowProcessor實現,但你能實現自定義版本的插件。也許最多見的自定義是實現toBean()方法處理自定義數據庫數據類型問題。
BasicRowProcessor使用一個BeanProcessor轉換ResultSet列到JavaBean屬性。你能在子類中覆蓋處理步驟處理針對你的應用程序的數據類型映射。提供實現表明數據類型轉換爲JDBC驅動程序。
BeanProcessor映射列到bean屬性記錄在BeanProcessor.toBean()的javadoc中。列名必須匹配bean的屬性名(忽略大小寫)。例如,firstname列能夠經過調用bean的setFirstName()方法存儲。然而,許多數據庫列名包括字符要麼不能使用要麼不是一般用於Java方法的名字。你能映射這些列到bean屬性:
在SQL中的列別名,因此它們能匹配Java名稱:select social_sec# as socialSecurityNumber from person
實現BeanProcessor並覆蓋mapColumnsToProperties()方法剔除攻擊性字符。