從獲得一千萬美元風(fēng)投開始算起剛滿一年,如今SpringSource(Spring框架背后的公司)搖身一變,成為應(yīng)用服務(wù)器提供商,并且舉著SpringSource應(yīng)用平臺(SpringSource Application Platform)的黃鉞白旄對現(xiàn)有的Java EE服務(wù)器陣營發(fā)起挑戰(zhàn)。SpringSource應(yīng)用平臺是構(gòu)建在Spring、OSGi和Apache Tomcat之上的應(yīng)用服務(wù)器,這個新的應(yīng)用服務(wù)器摒棄了原有的Java EE服務(wù)器標(biāo)準(zhǔn),自然而然地將Spring編程模型展現(xiàn)其中,隨之而來的還有一套基于OSGi內(nèi)核構(gòu)建的全新部署和打包系統(tǒng)。今天是該項目在SpringSource評估許可下Beta發(fā)布版發(fā)布的重要里程碑。在隨后一個月內(nèi)會有基于開源許可(GPLv3)版本和訂閱版本的通用發(fā)布版(General Availability,GA)放出。
SpringSource應(yīng)用平臺不是Java EE應(yīng)用服務(wù)器。盡管對于WAR部署它提供了支持,但EAR部署和其它EE的規(guī)范,如EJB等,都不在支持范圍之列。SpringSource應(yīng)用平臺被重新設(shè)計,并把關(guān)注點(diǎn)直接放在對被開源項目所廣泛使用的Spring組合的支持上。特別地,這個應(yīng)用服務(wù)器是基于Spring組合編程模型構(gòu)建的,利用Spring Dynamic Module實(shí)現(xiàn)基于OSGi的部署。SpringSource在Eclipse基金會的Equinox OSGi運(yùn)行時環(huán)境的基礎(chǔ)上創(chuàng)建了一個具備日志、跟蹤、啟動、類加載、管理和其它特性的“內(nèi)核”,Tomcat被作為一個包(bundle)納入到平臺當(dāng)中,從而實(shí)現(xiàn)對Web功能的支持。
InfoQ借此機(jī)會對Spring框架的共同創(chuàng)始人兼SpringSource的CEO Rod Johnson進(jìn)行一次采訪,對這個新的應(yīng)用服務(wù)器展開探討。在闡釋這個新平臺的必要性時,Rod一針見血地指向目前開發(fā)和生產(chǎn)環(huán)境的許多痛處,比如跨配置文件出現(xiàn)的元數(shù)據(jù)重復(fù)現(xiàn)象,還有本質(zhì)上在項目中常常在服務(wù)器上再部署服務(wù)器(即在部署應(yīng)用時,在同一個部署單元附帶部署許多工具和框架),而與此同時這些部件卻主要只使用它們應(yīng)用服務(wù)器中的Web容器部分的事實(shí)。因此,SpringSource希望在當(dāng)今的開發(fā)需要的基礎(chǔ)上提供一個更為簡單的平臺。
在談到這個新應(yīng)用服務(wù)器的優(yōu)點(diǎn)時,Johnson強(qiáng)調(diào)了模塊化:對于服務(wù)器本身以及提供給開發(fā)人員的打包和部署模式來說,這是個兩全之策。通過利用OSGi,以及OSGi包之間依賴關(guān)系相互作用的性質(zhì),運(yùn)行的應(yīng)用服務(wù)器只會激活在它上面運(yùn)行的應(yīng)用所需要的特性,從而削減服務(wù)器的內(nèi)存占用和啟動時間。這個依賴關(guān)系支持的功能還允許依賴類庫的多個版本共存,以支持不同應(yīng)用;因而應(yīng)用服務(wù)器的某些部分就可以很容易地更新和重啟,而無需重啟整個服務(wù)器。從開發(fā)的角度看,服務(wù)器的模塊化也使得在代碼變化時,可以很快地進(jìn)行極其細(xì)粒度的重部署。
Johnson在言及OSGi和SpringSource對Eclipse Equinox OSGi的使用時,高度評價了OSGi規(guī)范的運(yùn)行時實(shí)現(xiàn)所帶來的基礎(chǔ)平臺,但也表示OSGi在日常的應(yīng)用開發(fā)上屬于比較底層的地位。Johnson闡述到,SpringSource希望幫助開發(fā)人員在企業(yè)環(huán)境中輕松獲得價值。在新的編程模式的構(gòu)造背后,這個新的應(yīng)用服務(wù)器將OSGi的許多復(fù)雜性抽象了出來。Johnson接著說,應(yīng)用服務(wù)器將會支持PAR,一套新的可部署單元,簡化企業(yè)應(yīng)用在使用OSGi上的復(fù)雜性(下文會詳細(xì)說明)。
當(dāng)被問到對于沒有對OSGi提供原生支持的遺留類庫的支持時,Johnson回應(yīng)到,他們已經(jīng)在上面花費(fèi)了很大心血,使得應(yīng)用服務(wù)器環(huán)境和類加載功能能夠以兼容的方式和遺留類庫協(xié)作。
當(dāng)被問到對不提供OSGi原生支持的類庫的遺留支持時,Johnson回答說他們已經(jīng)在這方面投入了大量精力,保證應(yīng)用服務(wù)器環(huán)境和類加載功能可以和遺留類庫兼容工作。SpringSource還會為他們在如Tomcat之類的項目上所做的任何變更給這些項目提交補(bǔ)丁,使這些類庫可以和OSGi包兼容。
Johnson解釋到,應(yīng)用服務(wù)器的主題代碼將在GPL v3的許可證下發(fā)布。開發(fā)人員在服務(wù)器、編程模式和部署單元上要接觸到的所有部分都會以開源的形式提供。SpringSource還將提供應(yīng)用服務(wù)器的商業(yè)版本,包括支持、保障、管理和監(jiān)控的功能。
談到Spring應(yīng)用平臺發(fā)布之后對Spring組合繼續(xù)支持JavaEE有什么影響,Johnson回答說:
……我們從根本上說并不打算把Spring用戶社區(qū)驅(qū)趕到任何方向。我們僅僅是給用戶另一種選擇。Spring的哲學(xué)是用戶總是正確的。用戶是聰明的,他們完全明白自己的需要。不管用戶是否選擇SpringSource應(yīng)用平臺,我們覺得用戶總會歡迎多一點(diǎn)選擇的……
Johnson保證SpringSource一定會繼續(xù)確保Spring組合以及其他SpringSource產(chǎn)品兼容于其它應(yīng)用平臺。接著Johnson還評論了即將到來的Java EE 6規(guī)范:
Java EE 6重點(diǎn)在模塊性,這個方向是正確的。很可能SpringSource應(yīng)用服務(wù)器會在一定程度上符合Java EE 6。Java EE 6分成A、B、C三種規(guī)格(profile)。我們幾乎肯定會實(shí)現(xiàn)A和B規(guī)格,C規(guī)格里面我非常確定將實(shí)現(xiàn)Entity Beans 1.1模型以及一些遺留技術(shù)。我還不能說是100%確定,因?yàn)镴ava EE 6規(guī)范還沒有定案。
最后,InfoQ和Johnson討論到了SpringSource應(yīng)用平臺的大局方面。對于轉(zhuǎn)換到OSGi,他的回答是:
傳統(tǒng)的應(yīng)用服務(wù)器模型正逐漸過時。BEA和IBM正在用OSGi逐步重新實(shí)現(xiàn)他們的應(yīng)用服務(wù)器。 SpringSource現(xiàn)在就提供OSGi支持。從統(tǒng)計數(shù)字上看,大多數(shù)人都不會部署到完整的平臺上,他們部署到Tomcat。他們選擇了Spring 編程模型而非Java EE。市場已經(jīng)作出了選擇,問題只是開發(fā)者還要和服務(wù)器斗爭多長時間。
Johnson解釋說他對SpringSource應(yīng)用平臺成功的自信來自三個原因:
- 它是第一個建立在現(xiàn)代技術(shù)基礎(chǔ)上的產(chǎn)品。符合Java EE規(guī)范已經(jīng)不是至高無上的目標(biāo)。干凈的代碼基礎(chǔ)是我們的一項競爭優(yōu)勢。我們在設(shè)計和實(shí)現(xiàn)中滿足的是現(xiàn)今的需求,而不是10年前的需求。
- POJO編程是現(xiàn)在行業(yè)的方向所在。過去POJO編程是被強(qiáng)行嫁接到其它產(chǎn)品上的。在我們的產(chǎn)品中,POJO編程是設(shè)計的前提。
- SpringSource應(yīng)用平臺采用的OSGi技術(shù)是下一代技術(shù)的基礎(chǔ)。
除了Rod Johnson,InfoQ還與SpringSource的Rob Harrop探討了新應(yīng)用服務(wù)器的一些技術(shù)細(xì)節(jié)。對于與傳統(tǒng)Java EE應(yīng)用服務(wù)器相比有何增減,他說:
……JPA和JMS都支持,但我們沒有包含任何特定實(shí)現(xiàn)。對于JPA,我們支持Hibernate、 OpenJPA和Toplink。我們在OSGi環(huán)境中增加了對加載時織入的支持,而且會尊重應(yīng)用的邊界,因此不會意外污染應(yīng)用間共享的庫。不包括 JNDI,我們用OSGi Service Registry來取代它。Servlets是通過內(nèi)嵌的Tomcat來支持的。JEE中有而SpringSource應(yīng)用平臺沒有的東西包括 Entity Beans等等。
接下來InfoQ問到Spring Dynamic Modules。Spring DM成為公開項目已經(jīng)有一段時間了。對于模塊化部署,我們向Harrop詢問Spring DM是否增加了什么新東西:
這個平臺引入了應(yīng)用的概念,應(yīng)用由一個或多個Bundle組成。應(yīng)用中的包有明確的作用域,可以防止發(fā)生應(yīng)用間的沖突。在應(yīng)用把服務(wù)發(fā)布到OSGi service registry的情況下,防止沖突尤其重要,誰也不想見到服務(wù)之間發(fā)生沖突。
我們引入了Import-Library語句,因此在應(yīng)用中使用第三方庫變得更加簡單。你不需要再寫一大串不直觀的 Import-Package聲明,Import-Library可以自動為指定的庫引入所有必需的package。像Hibernate JPA這樣的庫還可以跨多個Bundle,可見Import-Library確實(shí)物有所值。
至于為了讓Spring DM在平臺中運(yùn)行而進(jìn)行的擴(kuò)展,為數(shù)不多。
Harrop接下來說明了新的PAR格式:
Spring DM掌控下的Bundle(Spring DM powered bundles)是包含META-INF/spring/*.xml文件的普通OSG Bundle。Bundle啟動的時候META-INF/spring/*.xml文件會自動成為該Bundle的 ApplicationContext。Spring DM提供了一種機(jī)制讓各Bundle通過Spring NamespaceHandler導(dǎo)入和導(dǎo)出服務(wù)。
一個PAR(Platform ARchive)本質(zhì)上是一組OSGi Bundle,通常其中有一部分是在Spring DM掌控下的。這些Bundle共同組成了一個邏輯上的應(yīng)用。編程的時候完全是純粹的OSGi、Spring和Spring DM——PAR沒有改變什么。
以前一般用Buddy Classloaders之類的技術(shù)來解決遺留/非OSGi庫的問題,SpringSource這次是怎么做的呢?Rob回答說:
簡單來說我們避免做這樣的事。Buddy類裝載、動態(tài)import、require-bundle,這些我們都明確回避,因?yàn)榫S持一致的類空間太困難了。我們也不會提供任何專有的替代機(jī)制。
相反,我們給Equinox增加了一些低級的鉤子,以實(shí)現(xiàn)典型的場景下的資源裝載。我們擴(kuò)展了類裝載來支持加載時織入,并且把裝載語義丟到一邊。我們操縱context classloader,讓第三方一如既往地看到類。PAR是其中的核心角色,因?yàn)樗x了上下文類裝載以及加載時織入的可見范圍。
對于一些最糟糕的情況,我們會提供修補(bǔ)版的庫,讓它們能在OSGi中工作。修補(bǔ)版的庫可以通過SpringSource Enterprise Bundle Repository獲得,我們的修改也會提交回相應(yīng)的項目。
最后Harrrop著重強(qiáng)調(diào)了這個應(yīng)用服務(wù)器在模塊化上的優(yōu)勢,應(yīng)用服務(wù)器因此可以維持最低的內(nèi)存占用。平臺在運(yùn)行中才設(shè)置依賴項,因此只有確實(shí)用到的依賴項才會被裝載。
最近幾年中有過許多關(guān)于Java EE標(biāo)準(zhǔn)是否已經(jīng)死亡的討論,而今天我們看到一個可能很重要的應(yīng)用服務(wù)器不帶Java EE支持。這種變化對于未來有何影響?你怎么看?
雖然現(xiàn)在出現(xiàn)了很多ORM框架,可是還是有很多朋友也許還在使用JDBC,就像我現(xiàn)在一樣,除了學(xué)習(xí)的時候在使用Hibernate、Spring類似這些優(yōu)秀的框架,工作時一直都在使用JDBC。本文就簡單介紹一下利用Jakarta Commons旗下beanutils、dbutils簡化JDBC數(shù)據(jù)庫操作,以拋磚引玉,希望對像我一樣在使用JDBC的朋友有所幫助。
下面就分兩部分簡單介紹beanutils、dbutils在基于JDBC API數(shù)據(jù)庫存取操作中的運(yùn)用。第一部分顯介紹beanutils在JDBC數(shù)據(jù)庫存取操作中的運(yùn)用,第二部分介紹dbutils在JDBC數(shù)據(jù)庫存取操作中的運(yùn)用,最后看看他們的優(yōu)缺點(diǎn),談?wù)劚救嗽陧椖窟\(yùn)用過程中對他們的一點(diǎn)心得體會,僅供參考,其中有錯誤的地方希望大蝦不吝賜教,大家多多交流共同進(jìn)步。
一、Jakarta Commons beanutils
Beanutils是操作Bean的銳利武器,其提過的BeanUtils工具類可以簡單方便的讀取或設(shè)置Bean的屬性,利用Dyna系列,還可以在運(yùn)行期創(chuàng)建Bean,符合懶人的習(xí)慣,正如LazyDynaBean,LazyDynaClass一樣,呵呵。這些用法已經(jīng)有很多文章提及,也可以參考apache的官方文檔。
對于直接利用JDBC API訪問數(shù)據(jù)庫時(這里針對的是返回結(jié)果集ResultSet的查詢select),大多數(shù)都是采用兩種方式,一種是取出返回的結(jié)果集的數(shù)據(jù)存于Map中,另一種方式是Bean里。針對第二種方式,Beanutils里提供了ResultSetDynaClass結(jié)合DynaBean以及RowSetDynaClass結(jié)合DynaBean來簡化操作。下面用以個簡單的例子展示一下beanutils的這兩個類在JDBC數(shù)據(jù)庫操作中的運(yùn)用。
請在本機(jī)建立數(shù)據(jù)庫publish,我用的是MySQL,在publish數(shù)據(jù)庫中建立表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來實(shí)現(xiàn)同樣的類,之后看看他們之間有什么不同,用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;
}
}
這兩個方法輸出的結(jié)果應(yīng)該是一樣的。但是很顯然第二種方式比第一種方式要好,它把數(shù)據(jù)訪問部分抽取出來放到一個方法中,顯得簡單清晰。
其實(shí)在利用ResultSetDynaClass時,必須在ResultSet等數(shù)據(jù)庫資源關(guān)閉之前,處理好那些數(shù)據(jù),你不能在資源關(guān)閉之后使用DynaBean,否則就會拋出異常,異常就是說不能在ResultSet之后存取數(shù)據(jù)(具體的異常名我也忘了),當(dāng)然你也可以采用以前的方式一個一個的把數(shù)據(jù)放到Map里,如果你一定要那樣做,建議還是別用Beanutils,因?yàn)檫@沒帶給你什么好處??傊肦esultSetDynaClass你的程序的擴(kuò)展性非常部好。
從第二中方式可以看出,利用RowSetDynaClass可以很好的解決上述ResultSetDynaClass遇到的問題,RowSetDynaClass的getRows()方法,把每一行封裝在一個DynaBean對象里,然后,把說有的行放到一個List里,之后你就可以對返回的List里的每一個DynaBean進(jìn)行處理,此外對于DynaBean你還可以采用標(biāo)準(zhǔn)的get/set方式處理,當(dāng)然你也可以用PropertyUtils. getSimpleProperty(Object bean, String name)進(jìn)行處理。
從上面的分析中,你應(yīng)該可以決定你應(yīng)該使用ResultSetDynaClass還是RowSetDynaClass了。
未完待續(xù)……
=============================
二、Jakarta Commons dbutils:
用JDBC API時最令人討厭的就是異常處理,也很煩瑣,而且很容易出錯,本人曾考慮過利用模板進(jìn)行處理,后來看到了dbutils,之后就采用那個dbutils,采用模板的方式各位朋友可以參考Spring,Spring的JdbcTemplate不靈活而強(qiáng)大,呵呵,說句閑話,實(shí)在太佩服Rod Johnson了,Rod Johnson真的很令人尊敬。
Dbutils的QueryRunner把大多數(shù)與關(guān)閉資源相關(guān)的封裝起來,另外,你也可以使用DbUtils進(jìn)行關(guān)閉,當(dāng)然DbUtils提供的功能當(dāng)然不止這些,它提過了幾個常用的靜態(tài)方法,除了上述的關(guān)閉資源外,DbUtils. commitAndClose(Connection conn)還提供事務(wù)提及等操作。
還是以一個例子來說說吧,畢竟我不是搞業(yè)務(wù)的,小嘴巴吧嗒吧噠不起來啊,呵呵。
為了和采用Beanutils更好的進(jìn)行對比,這個例子還是實(shí)現(xiàn)同樣的功能,數(shù)據(jù)庫同樣采用前一篇文章中提到的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的方式代替進(jìn)行處理
List lMap = (List) qRunner.query(conn,
"select title,authors from books", new MapListHandler());
//以下是處理代碼,可以抽取出來
System.out.println("title ------------- authors ");
for (int i = 0; i < lMap.size(); 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令人難纏的是關(guān)閉那些資源以及處理那些異常,而這里采用Dbutils顯然代碼量減少了很多。
上例在處理結(jié)果集時,它把數(shù)據(jù)庫中的每一行映射成一個Map,其中列名作為Key,該列對應(yīng)的值作為Value存放,查詢的所有的數(shù)據(jù)一起放在一個List里,然后進(jìn)行處理,當(dāng)然,一個更明智的處理是直接返回List然后再單獨(dú)進(jìn)行處理。
事實(shí)上上例返回的結(jié)果集中的每一行不必放在一個Map里,你可以放在一個Bean里,當(dāng)然如果你真的很懶,你也可以使用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的方式代替進(jìn)行處理
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 < lBeans.size(); i++) {
Book vals = (Book) lBeans.get(i);
System.out.println(vals.getTitle ()+"-------------"+ vals. getAuthors ());
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
DbUtils.closeQuietly(conn);
}
}
}
這兩種法輸出的結(jié)果應(yīng)該是一樣的。兩種處理方式都差不多,但我更愿意采用第一種,因?yàn)榈谝环N少寫一個bean,而且我測試過采用Map的方式即第一種方式性能要好的多,采用Bean性能比較低可能是因?yàn)椴捎梅瓷涞木壒?,采用反射的東東性能和不采用反射的還是有點(diǎn)差距。也是這個原因,不推薦采用LazyDynaClass和LazyDynaBean,因?yàn)椴捎眠@二者是在運(yùn)行期動態(tài)創(chuàng)建Bean類和Bean屬性,然后再創(chuàng)建Bean對象的,其性能可想而知了(不過我沒有測試過啊,所以我說這個話可說是沒有根據(jù)的,感興趣的朋友自己測試一下,記得告訴我結(jié)果哦,呵呵),除了MapListHandler以及BeanListHandler之外,DButils還提供了其他的Handler,如果這些不能滿足你的需求,你也可以自己實(shí)現(xiàn)一個Handler。
最后,也是最大的體會,也許是最大的收獲吧,那就是:對于每一個項目,在根據(jù)每一個需求獲取相應(yīng)解決方案時,先尋找開源組件,看是否已經(jīng)有滿足某些功能需求的開源組件,如果沒有,再考慮自主開發(fā)或者向第三方購買,否則盡量采用開源組件.
請盡量享用開源的魅力,盡情的擁抱開源吧。
| |||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
---|---|---|---|---|---|---|---|---|---|
25 | 26 | 27 | 28 | 29 | 30 | 31 | |||
1 | 2 | 3 | 4 | 5 | 6 | 7 | |||
8 | 9 | 10 | 11 | 12 | 13 | 14 | |||
15 | 16 | 17 | 18 | 19 | 20 | 21 | |||
22 | 23 | 24 | 25 | 26 | 27 | 28 | |||
29 | 30 | 1 | 2 | 3 | 4 | 5 |