高性能jdbc封装工具 Apache Commons DbUtils 1.6(转载)
轉(zhuǎn)載自原文地址:http://gao-xianglong.iteye.com/blog/2166444
前言
關(guān)于Apache的DbUtils中間件或許了解的人并不多,大部分開發(fā)人員在生成環(huán)境中更多的是依靠Hibernate、Ibatis、Spring JDBC、JPA等大廠提供的持久層技術(shù)解決方案,或者是企業(yè)內(nèi)部自己研發(fā)的持久層技術(shù)。但無論如何,使用這些技術(shù)的初衷和本質(zhì)都是為了能夠減少企業(yè)開發(fā)成本,提高生產(chǎn)效率,降低耦合。
?
放眼企業(yè)級項(xiàng)目,Hibernate等ORM產(chǎn)品是首選,而互聯(lián)網(wǎng)領(lǐng)域,大部分開發(fā)人員往往并不會在生產(chǎn)環(huán)境中上這些ORM技術(shù),原因很簡單,要的就是效率,其次都不重要。對于剛接觸SQL和JDBC的開發(fā)人員,最引以為傲的就是希望能夠在日后編寫復(fù)雜的SQL語句,以及會使用諸如Hibernate、Ibatis等第三方持久層技術(shù),并且極力的撇清與傳統(tǒng)JDBC技術(shù)的關(guān)系,但筆者不得不認(rèn)為,這是一種普遍業(yè)界存在的“病態(tài)”!
?
如果是企業(yè)級的項(xiàng)目,尤其是跟金融相關(guān)的業(yè)務(wù),SQL語句或許會非常復(fù)雜,并且關(guān)聯(lián)著事物。但互聯(lián)網(wǎng)項(xiàng)目卻并非如此,在互聯(lián)網(wǎng)項(xiàng)目中,看你牛不牛逼并不是取決于你能否寫出一條復(fù)雜的SQL語句,而是看你能否將原本一條復(fù)雜的SQL語句拆散成單條SQL,一句一句的執(zhí)行;并且脫離Hibernate等ORM產(chǎn)品后,能否使用傳統(tǒng)的JDBC技術(shù)完成一條簡單的CRUD操作,這才是牛逼!是的,你沒有聽錯,互聯(lián)網(wǎng)確確實(shí)實(shí)就是這么玩,還原最本質(zhì)的東西,才是追求性能的不二選擇。
?
筆者本章不會提及垂直分庫、水平分區(qū)等數(shù)據(jù)庫概念,以及數(shù)據(jù)路由中間件等技術(shù)(請閱讀筆者博文《剖析淘寶TDDL—Matrix層分庫分表實(shí)現(xiàn)》),因?yàn)檫@些內(nèi)容與本章內(nèi)容無關(guān),但間接來看,筆者之前提及的單條SQL、使用JDBC完成基本的CRUD操作就可以在最大程度上滿足一個互聯(lián)網(wǎng)場景的持久層操作。以Hibernate為例,簡單來說需要經(jīng)歷HQL->SQL->DBMS等編譯過程,中間還冗余著緩存、對象等開銷,希望大家記住,封裝層次越高,性能越低!這個是無可爭議的事實(shí)。筆者希望大家接下來,暫時“忘記”掉你所會的持久層技術(shù),耐心的聽筆者為你介紹Apache的DbUtils技術(shù),或許你會有意想不到的收獲。
?
目錄
一、Apache Commons DbUtils簡介;
二、下載與安裝DbUtils;
三、使用DbUtils完成CRUD操作;
四、C3P0連接池集成DbUtils;
五、常用包、類講解;
六、自動封裝結(jié)果集;
七、事物管理;
?
一、Apache Commons DbUtils簡介;
Apache的DbUtils工具是一個輕量級的持久層解決方案,天生為性能而生,它簡單的對JDBC進(jìn)行了必要的操作封裝,讓開發(fā)人員能夠以一種高級API的方式使用JDBC技術(shù)完成原本復(fù)雜的CRUD操作。換句話說,DbUtils天生就不是一個復(fù)雜的技術(shù),它只是一個簡單的JDBC上層封裝,對開發(fā)人員而言,大概只需半小時就能夠完全掌握DbUtils技術(shù)的使用,是的,它就是這么簡單與方便,它是互聯(lián)網(wǎng)項(xiàng)目的寵兒,選擇DbUtils技術(shù)作為持久層的解決方案,或許能夠讓你從原本復(fù)雜的Hibernate操作中解脫出來,或者是你覺得Ibatis不夠好用,DbUtils也是你選擇的理由之一。總之,使用它,你將會感到驚艷,它是如此的簡單和干凈,如此的純粹和高效!并且DbUtils是采用商業(yè)友好的開源協(xié)議,大家甚至可以下載它的源碼,進(jìn)行二次開發(fā),以此滿足企業(yè)自身的需要。
?
二、下載與安裝DbUtils;
當(dāng)大家對DbUtils的項(xiàng)目背景有所了解后,接下來本節(jié)內(nèi)容筆者將會告訴你它的下載和安裝。大家可以登錄http://commons.apache.org/站點(diǎn)下載DbUtils工具的最新版本,筆者使用的版本為1.6.0,在此大家需要注意,為了避免在開發(fā)過程中出現(xiàn)異常,建議大家下載、使用與筆者本篇博文一致的版本。
?
當(dāng)大家成功下載好DbUtils相關(guān)的構(gòu)件后,我們可以將其添加到項(xiàng)目中的ClassPath目錄下,當(dāng)然筆者后續(xù)小節(jié)會提及DbUtils與C3P0連接池的集成,因此,大家最好將C3P0所需的構(gòu)件以及數(shù)據(jù)庫驅(qū)動(筆者使用Mysql)一起添加到項(xiàng)目中。使用DbUtils時關(guān)聯(lián)的構(gòu)件,如下所示:
?
3、使用DbUtils完成CRUD操作;
廢話不多說,使用DbUtils操作數(shù)據(jù)庫之前,首先要做的事情就是獲取Connection。那么為了方便,筆者使用硬編碼的方式將數(shù)據(jù)源的配置信息coding在代碼中(生產(chǎn)環(huán)境中,有可能是配置在項(xiàng)目的配置文件中、數(shù)據(jù)庫中、Diamond中等),如下所示:
Java代碼???
當(dāng)編寫好ConnectionManager之后,接下來要做的事情就是獲取Connection,然后就能夠使用DbUtils進(jìn)行CRUD操作了。或許細(xì)心的讀者已經(jīng)發(fā)現(xiàn),使用DbUtils其實(shí)是非常簡單的,需要會的不多,僅僅只需要掌握J(rèn)DBC操作以及簡單的CRUD操作即可(互聯(lián)網(wǎng)場景下同樣也是這么要求)。
Java代碼???
四、C3P0連接池集成DbUtils;
在生產(chǎn)環(huán)境中,開發(fā)人員在對數(shù)據(jù)庫進(jìn)行CRUD操作的時候,由于數(shù)據(jù)庫的鏈接是有限的,因此不得不使用連接池來實(shí)現(xiàn)資源復(fù)用,以此降低數(shù)據(jù)庫的性能瓶頸(盡管這么說有些不太友好,因?yàn)椴l(fā)環(huán)境下,單靠連接池是不能夠解決問題的,而常用的方案更多是諸如Redis之類的內(nèi)存數(shù)據(jù)庫抗住70%傳統(tǒng)DBMS數(shù)據(jù)的受訪壓力、數(shù)據(jù)庫先做垂直分庫,再做水平分區(qū),當(dāng)然Master/Sleave是必不可少的,經(jīng)過這些步驟之后,才能夠說基本上解決了理論上可能出現(xiàn)的數(shù)據(jù)庫在高并發(fā)環(huán)境下的瓶頸)。
?
廢話不多說,在之前的ConnectionManager中添加進(jìn)連接池相關(guān)的代碼,當(dāng)然為了方便,筆者同樣還是使用硬編碼的方式,如下所示:
Java代碼???
當(dāng)成功在ConnectionManager中添加好所需的C3P0連接池配置后,接下來要做的事情就是考慮如何使用C3P0與DbUtils之間的集成。其實(shí)最簡單的做法就是直接將之前獲取Connection的getConnection()方法更換為上述代碼中的getConnection2()即可,同樣可以使用在創(chuàng)建QueryRunner實(shí)例時,將數(shù)據(jù)源的DataSource傳遞過去,這樣即可避免在執(zhí)行CRUD操作時,還需要在方法中指明Connection。
?
當(dāng)然究竟應(yīng)該怎么做,完全取決于你自己,如果希望方便,那么筆者建議你在創(chuàng)建QueryRunner實(shí)例時,直接將C3P0的DataSource傳遞過去,但這樣做的弊端很明顯,如果在特殊的場景下,需要手動控制事物時,那么這種操作是極其不便的,因?yàn)镃onnection并不可控。那么為了解決事物控制的問題,當(dāng)然是Connection可控最好。
?
五、常用包、類講解;
相信大家已經(jīng)從上述DbUtils的CRUD示例中發(fā)現(xiàn)了QueryRunner的身影,那么筆者接下來就將會針對DbUtils中諸如QueryRunner等常用類型進(jìn)行深入講解。
?
在DbUtils中,最常用的3個包為org.apache.commons.dbutils、org.apache.commons.dbutils.handlers以及org.apache.commons.dbutils.wrappers。
org.apache.commons.dbutils包下的常用類,如下所示:
1、DbUtils : 提供如關(guān)閉連接、裝載 JDBC 驅(qū)動程序等常規(guī)工作的工具類;
2、QueryRunner : 該類簡單化了 SQL 查詢,它常與與 ResultSetHandler 組合在一起使用;
org.apache.commons.dbutils.handlers包下的常用類,如下所示:
1、ArrayHandler :將ResultSet中第一行的數(shù)據(jù)轉(zhuǎn)化成對象數(shù)組;
2、ArrayListHandler:將ResultSet中所有的數(shù)據(jù)轉(zhuǎn)化成List,List中存放的是Object[];
3、BeanHandler :將ResultSet中第一行的數(shù)據(jù)轉(zhuǎn)化成類對象;
4、BeanListHandler :將ResultSet中所有的數(shù)據(jù)轉(zhuǎn)化成List,List中存放的是類對象;
5、ColumnListHandler :將ResultSet中某一列的數(shù)據(jù)存成List,List中存放的是Object對象;
6、KeyedHandler :將ResultSet中存成映射,key為某一列對應(yīng)為Map。Map中存放的是數(shù)據(jù);
7、MapHandler :將ResultSet中第一行的數(shù)據(jù)存成Map映射;
8、MapListHandler :將ResultSet中所有的數(shù)據(jù)存成List。List中存放的是Map;
9、ScalarHandler :將ResultSet中一條記錄的其中某一列的數(shù)據(jù)存成Object;
org.apache.commons.dbutils.wrappers包下的常用類,如下所示:
1、SqlNullCheckedResultSet :該類是用來對sql語句執(zhí)行完成之后的的數(shù)值進(jìn)行null的替換;
2、StringTrimmedResultSet :去除ResultSet中中字段的左右空格;
?
六、自動封裝結(jié)果集;
在org.apache.commons.dbutils.handlers包下的類型,大部分都是與查詢結(jié)果集相關(guān)的。試想一下,利用傳統(tǒng)的JDBC進(jìn)行查詢時,返回的數(shù)據(jù)我們需要對ResultSet進(jìn)行迭代,這是相當(dāng)麻煩的,且不利于維護(hù),因?yàn)槲覀冃枰?span style="color:#800000;">手動編寫與之相關(guān)的數(shù)據(jù)封裝。但是使用DbUtils之后,我們要做的事情僅僅只是告訴DbUtils我們需要什么樣的數(shù)據(jù)即可,關(guān)于數(shù)據(jù)封裝這種通用的控制邏輯,則無需開發(fā)人員參與,這極大的節(jié)省了開發(fā)人員的時間,提升了生產(chǎn)效率。
?
簡單來說,筆者在開發(fā)過程中使用最廣泛的就是BeanListHandler以及MapListHandler 封裝的結(jié)果集。簡單來說,BeanListHandler將會查詢后的數(shù)據(jù)封裝到一個對應(yīng)的POJO中(可以看做是一個無狀態(tài)的實(shí)體Bean),MapListHandler 會將查詢后的數(shù)據(jù)封裝為一個List,List中存儲的就是一個個的Map集合,通過key-value的方式獲取封裝后的數(shù)據(jù)集。先來看看MapListHandler 的使用,如下所示:
Java代碼???
如果你喜歡類似于實(shí)體Bean的操作方式,那么BeanListHandler無疑使最好的選擇。一旦我們使用BeanListHandler作為數(shù)據(jù)返回后的結(jié)果集封裝,那么DbUtils便會將查詢后的結(jié)果集一個字段一個字段的映射到指定的POJO中,當(dāng)然前提就是字段名稱是必須一致的,否則DbUtils將無法完成數(shù)據(jù)封裝。BeanListHandler的使用示例,如下所示:
Java代碼???
在此大家需要注意,為了方便演示,筆者在此并沒有提供對應(yīng)的POJO。如果有需要,大家可以編寫一個與數(shù)據(jù)庫表字段相同的POJO來完成查詢結(jié)果集的字段映射封裝操作。
?
七、事物管理;
說起事物管理,這其實(shí)是一個非常復(fù)雜與繁瑣,且是最容易出錯的場景,尤其是在手動管理事物操作上。當(dāng)然本節(jié)所提及的事物管理仍然是建立在基于手動管理的事物操作上。對于JDBC操作,如果希望事物不要手動提交,那么在獲取Connection的時候,一定需要將設(shè)置conn.setAutoCommit(false);這樣一來事物就不會自動進(jìn)行提交,當(dāng)我們手動執(zhí)行conn.commit()方法的時候,事物才會進(jìn)行提交。這種方式對于DbUtils其實(shí)是一樣的,之前也說過,DbUtils僅僅只是對JDBC做了一個輕量級的上層封裝,那么必然可以和JDBC進(jìn)行混用,一旦我們在程序中設(shè)定了事物后,接下來的事物管理操作就依賴與開發(fā)人員自身了,DbUtils將不會再參與事物的管理。
?
對于大多數(shù)開發(fā)人員而言,事物控制的不好,將會導(dǎo)致業(yè)務(wù)出現(xiàn)問題,臟數(shù)據(jù)等情況是非常常見的,但從另一個層面來說,手動的事物管理其實(shí)是最靈活和方便的。在此需要提醒大家,如果是使用Mysql數(shù)據(jù)庫,只有將數(shù)據(jù)庫引擎設(shè)置為InnoDB后,才會支持事物!
?
最后筆者在啰嗦一下,使用完資源后,我們一定要記得及時釋放掉資源,以此避免無用資源長時間掛起。那么在DbUtils中,你將有2種方式結(jié)束掉Connection,第一個是使用DbUtils.close()方法。其次,你將可以直接使用close()方法關(guān)閉Connection的鏈接
轉(zhuǎn)載于:https://www.cnblogs.com/firstdream/p/4892184.html
總結(jié)
以上是生活随笔為你收集整理的高性能jdbc封装工具 Apache Commons DbUtils 1.6(转载)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (软件工程复习核心重点)第七章软件维护-
- 下一篇: 汇编四则运算