电竞比分网-中国电竞赛事及体育赛事平台

分享

Spring與iBATIS的集成

 pablo3518 2007-07-16
轉(zhuǎn)載聲明:版權(quán)規(guī)文章原創(chuàng)作者所有
轉(zhuǎn)載時(shí)間:2007年07月16日
轉(zhuǎn)載作者:pablo3518
Spring與iBATIS的集成
iBATIS似乎已遠(yuǎn)離眾說(shuō)紛紜的OR框架之列,通常人們對(duì)非常流行的Hibernate情有獨(dú)鐘。但正如Spring: A Developer‘s Notebook作者Bruce Tate 和Justin Gehtland所說(shuō)的那樣,與其他的OR框架相比,iBATIS獨(dú)辟蹊徑:“iBATIS不是試圖從根本上掩蓋SQL,實(shí)際上,它是在擁抱SQL。”

但別犯愁:SQL本身具備了一些重要的功能,并且通過(guò)模板的使用,在Spring應(yīng)用中采用iBATIS顯得輕而易舉。在此摘錄中,兩位作者將和你一起安裝iBATIS并將其集成進(jìn)你的Spring應(yīng)用中。他們也闡明了怎樣取得你已編寫的SQL語(yǔ)句及把他們映射給iBATIS使用的Bean。最后,還討論了iBATIS的優(yōu)缺點(diǎn),及為什么是這樣的一種方式,即所謂的“在完全OR與JDBC之間的一個(gè)幽雅的折衷。”

就象Developer‘s Notebook 系列中所有的書一樣,你將由直接的且實(shí)用的方式獲得信息,這些信息包含了完成你工作所需的細(xì)節(jié)。換言之:“一切來(lái)自實(shí)戰(zhàn),沒有講義。”

作者:czyczy
原文:http://www./resource/article/44/44304_Spring+iBATIS.html
關(guān)鍵字:Spring;iBATIS

對(duì)象關(guān)系持久化(OR Persistence)

本章所涉及的內(nèi)容為:
· 與iBATIS的集成
· 在Spring的應(yīng)用中使用JDO
· 在Spring的應(yīng)用中使用Hibernate
· 運(yùn)行測(cè)試用例


離我住處不遠(yuǎn)的地方,名為啤酒山的山上有一個(gè)臭名遠(yuǎn)揚(yáng)的山地自行車道。我想不出它為何會(huì)得到這樣的名字,因?yàn)樵谙律降臅r(shí)候你要保持完全地清醒甚至于全神貫注。據(jù)我所知,那決不是純粹的攀爬(或不曾離開自行車步行)。大多數(shù)人認(rèn)為那很荒謬,哪怕只是去嘗試一下而已。這座山連綿起伏,異常陡峭,它的表面覆蓋了松散的巖石和大量的巖脊。我想我一定是太厭煩我的余生了,因?yàn)閮赡臧雭?lái)我一直不斷地在攀爬。在我看來(lái),那樣的一座山峰就像是一個(gè)困難的編程問題。我已多次重新啟程,在到達(dá)山峰的途中,嘗試過(guò)翻越許多巖脊和泥礫叢的不同途徑。為了攀爬啤酒山, 我需要改良自行車,提高車技,加強(qiáng)訓(xùn)練。

對(duì)Java 開發(fā)人員而言,對(duì)象關(guān)系映射已然成為那類問題了。我們需要處理功能(processing power)、較佳設(shè)計(jì)模式及更好持久化框架的組合,從而使解決持久化設(shè)計(jì)變得更加清晰。最終,我們開始取得實(shí)質(zhì)性的進(jìn)展?,F(xiàn)在,我們已逼近山峰,象Spring這樣的框架就象是方程式的一部分,因?yàn)樗麄冏寣?duì)象關(guān)系映射(ORM)花較少的精力來(lái)做更多的事情。在本章中,你將看到三種框架:iBATIS, JDO及Hibernate:

·iBATIS 是一種JDBC助手類框架,它給了你一些OR映射及使用OR的好處,但不帶 有太多的風(fēng)險(xiǎn)。
·JDO是一種飽受爭(zhēng)議的持久化標(biāo)準(zhǔn),但它有著一些獨(dú)特的實(shí)現(xiàn),這使得JDO在行業(yè)中也算得上是最完美的持久化框架之一。
·Hibernate 是在JBoss組織控制下的一開源持久化框架。它可能是時(shí)下最為流行的持久化框架。大量的客戶采用它,而且客戶的數(shù)量還在持續(xù)穩(wěn)定地增長(zhǎng)。        

在本章中,我們會(huì)對(duì)所提的三個(gè)框架進(jìn)行嘗試,而不必對(duì)應(yīng)用的其余部分的代碼做任何變更。

與iBATIS集成

常言道:“樹大招風(fēng)”。在大肆宣揚(yáng)的J2EE和.Net之爭(zhēng)中, Sun的一示例應(yīng)用程序被用來(lái)作為衡量應(yīng)用服務(wù)器在運(yùn)行時(shí)的各項(xiàng)性能的核心基準(zhǔn)。 .Net非常好地打敗了基于EJB的J2EE版本, 且方興未艾。Clinton Begin 開發(fā)了iBATIS的持久化框架,他在iBATIS中使用PetStore的簡(jiǎn)化版,且自從那以后iBATIS就越來(lái)越流行。Spring提供非常優(yōu)良的與iBATIS的集成功能, 在此章中將對(duì)其進(jìn)行介紹。

并非所有的問題都非常適合持久化框架這朵盛開的花朵,中等難度的問題是最合適的環(huán)境。沒有正確的技巧或不相稱的問題,可能就會(huì)誤入歧途。跟我一起教課的Ted Neward, 他是《Effective Enterprise Java》一書的作者,他經(jīng)常把構(gòu)建或采用持久化框架與美國(guó)的越南戰(zhàn)爭(zhēng)拿來(lái)做比較,進(jìn)入這樣的兩場(chǎng)戰(zhàn)爭(zhēng)是很誘人的,但最終都很難贏得勝利,而且此二例中并不存在著行之有效的策略。關(guān)于這一話題,你仍可查閱http://www.上的相關(guān)內(nèi)容。

然而,我不想扯得太遠(yuǎn)。嘗試一下象iBATIS SqlMaps的框架給了你OR的使用模型又何嘗不可呢?當(dāng)然,我們不會(huì)強(qiáng)迫你一口吞下一只大象。具體來(lái)說(shuō),iBATIS讓你:
·映射字段和SQL語(yǔ)句到關(guān)鍵字
·使用SQL的全部功能而沒有乏味的JDBC
·從你的代碼中剝離SQL
Spring 與iBATIS的集成給了你這些及更多的裨益, 讓我們?yōu)榇硕跗饋?lái)。

我該怎么做?


首先,你需要安裝iBATIS。由于iBATIS的配置會(huì)在你的Spring 應(yīng)用上下文中完成,因此你不需要立即配置它。在http://www./(譯注:最新的網(wǎng)址為:http://ibatis./,iBATIS已于2004-08-16并入Apache 軟件基金會(huì))上可以下載并安裝。在本書中我們使用1.3.1版本。把iBATIS提供的jars(ibatis-sqlmap.jar, ibatis-dao.jar, and ibatis-common.jar)和Spring提供的jdom.jar(在Spring的/lib 目錄下)放到你的項(xiàng)目目錄/war/WEB-INF/lib中。

You’ve already got the interface for the façade and the model, so you need an implementation of the façade and the SQL statement.   First, you can implement the façade for the application, as in Example 5-1.
你已經(jīng)有了門戶(façade)和模型(model)的接口,因而你需要facade和SQL語(yǔ)句的實(shí)現(xiàn)。首先,你可以象示例5-1那樣,在你的應(yīng)用中實(shí)現(xiàn)façade的接口。

示例 5-1 IBatisRentABike.java

public class IBatisRentABike extends SqlMapDaoSupport
                  implements RentABike {

         private String storeName ="";

         public void setStoreName(String storeName) {
                 this.storeName= storeName;
         }

         public String getStoreName( ) {
                 return this.storeName;
         }

         public List getBikes() {
                 return getSqlMapTemplate().executeQueryForList("getBikes", null);
         }

         public Bike getBike(String serialNo) {
                 return (Bike) getSqlMapTemplate().
                         executeQueryForObject("getBikeBySerialNo", serialNo);
         }

         public Bike getBike(int bikeId) {
                 return (Bike) getSqlMapTemplate().
                         executeQueryForObject("getBikeByID", new Integer(bikeId));
         }

         public void saveBike(Bike bike) {
                 getSqlMapTemplate().executeUpdate("saveBike", bike);
         }

         public void deleteBike(Bike bike) {
                 getSqlMapTemplate().executeUpdate("deleteBike", bike);
         }

         public List getCustomers() {
                 return getSqlMapTemplate().executeQueryForList("getCustomers", null);
         }

         public Customer getCustomer(int custId) {
                 return (Customer) getSqlMapTemplate().
                     executeQueryForObject("getCustomer", new Integer(custId));
         }
        
         public List getReservations() {
                 return getSqlMaptemplate().
                     executeQueryForList("getReservations", null);
         }

         public List getReservations(Customer customer) {
                 return getSqlMaptemplate().
                     executeQueryForList("getReservationsForCustomer", customer);
         }

         public List getReservations(Bike bike) {
                 return getSqlMaptemplate().
                     executeQueryForList("getReservationsForBike",bike);
         }

         public List getReservations(Date date) {
                 return getSqlMaptemplate().
                     executeQueryForList("getReservationsForDate", date);
         }

         public Reservation getReservation(int resId) {
                 return getSqlMaptemplate().
                     executeQueryForObject("getReservation", new Integer(resId));
         }
}


這些就是命名式查詢。iBATIS將每一查詢分成一個(gè)獨(dú)立的映射,那樣你就可以用名字來(lái)執(zhí)行查詢。

SqlMapTemplate由Spring的SqlMapDaoSupport 類提供,我們的RentABike實(shí)現(xiàn)必須來(lái)繼承這個(gè)類。SqlMapTemplate負(fù)責(zé)建立和管理底層數(shù)據(jù)存儲(chǔ)的連接,同時(shí)也解釋了你所提供的映射文件。你可以把template 看成是你對(duì)于iBATIS命名式查詢所做那些事情的默認(rèn)實(shí)現(xiàn)。

你也需要?jiǎng)?chuàng)建SQL語(yǔ)句,可以給每條SQL語(yǔ)句取一個(gè)名字。然后,把結(jié)果映射給Java Bean。在這里你有兩種選擇,你可以在SQL中把每個(gè)Bean屬性作為別名來(lái)引用,或在查詢和Bean 之間建立顯式映射,就象示例5-2那樣。在此例中我們也建立了Customer 與Reservation的映射。

示例5-2.   Bike.xml(iBATIS SQL 映射文件)
<?xml version="1.0" encoding="UTF-8" ?>


<sql-map name="Bike" >
     <result-map name="result" class="com.springbook.Bike" >
        <property name="bikeId" column="bikeId" columnIndex="1" />
        <property name="manufacturer" column="manufacturer" columnIndex="2" />
        <property name="model" column="model" columnIndex="3" />
        <property name="frame" column="frame" columnIndex="4" />
        <property name="serialNo" column="serialNo" columnIndex="5" />
        <property name="weight" column="weight" columnIndex="6" />
        <property name="status" column="status" columnIndex="7" />
     </result-map>
    
     <mapped-statement name="getBikes" result-map="result">
         select bikeId, manufacturer, model, frame, serialNo, status
         from bikes
     </mapped-statement>

     <mapped-statement name="getBikeBySerialNo" result-map="result">
         select bikeId, manufacturer, model, frame, serialNo, status
         from bikes
        where serialNo=#value#
     </mapped-statement>

     <mapped-statement name="getBikeByID" result-map="result">
         select bikeId, manufacturer, model, frame, serialNo, weight, status
         from bikes
         where bikeId=#value#
     </mapped-statement>

     <mapped-statement name="saveBike" >
         insert into bikes
         (bikeId, manufacturer, model, frame, serialNo, weight, status)
         values(#bikeId#, #manufacturer#, #model#, #frame#, #serialNo#,
         #weight#, #status#)
     </mapped-statement>

     <mapped-statement name="deleteBike" >
         delete from bikes
         where bikeId = #bikeId#
     </mapped-statement>
</sql-map>


示例5-3. Customer.xml
<?xml version="1.0" encoding="UTF-8" ?>


<sql-map name="Customer" >
     <result-map name="result" class="com.springbook.Customer" >
        <property name="custId" column="custId" columnIndex="1" />
        <property name="firstName" column="firstName" columnIndex="2" />
        <property name="lastName" column="lastName" columnIndex="3" />
     </result-map>
    
     <mapped-statement name="getCustomers" result-map="result">
             select custId,
                     firstName,
                     lastName
              from customers
     </mapped-statement>

     <mapped-statement name="getCustomer" result-map="result">
             select custId,
                     firstName,
                     lastName
             from customers
             where custId = #value#
     </mapped-statement>
</sql-map>


示例 5-4. Reservation.xml
<?xml version="1.0" encoding="UTF-8" ?>


<sql-map name="Reservation" >
     <result-map name="result" class="com.springbook.Customer" >
        <property name="reservationId" column="resId" columnIndex="1" />
        <property name="bike" column="bikeId" columnIndex="2" />
        <property name="customer" column="custId" columnIndex="3" />
        <property name="reservationDate" column="resDate" columnIndex="4" />
     </result-map>
    
     <mapped-statement name="getReservations" result-map="result">
             select resId,
                    bikeId,
                               custId,
                               resDate           
              from reservations
     </mapped-statement>

     <mapped-statement name="getReservationsForCustomer" result-map="result">
             select resId,
                    bikeId,
                               custId,
                               resDate           
              from reservations
              where custId = #value#
     </mapped-statement>

     <mapped-statement name="getReservationsForBike" result-map="result">
             select resId,
                    bikeId,
                               custId,
                               resDate           
              from reservations
              where bikeId = #value#
     </mapped-statement>

     <mapped-statement name="getReservationsForDate" result-map="result">
             select resId,
                    bikeId,
                               custId,
                               resDate           
              from reservations
              where resDate = #value#
     </mapped-statement>

     <mapped-statement name="getReservation" result-map="result">
             select resId,
                    bikeId,
                               custId,
                               resDate           
              from reservations
              where resId = #value#
     </mapped-statement>
</sql-map>


The <result-map> portion provides an explicit map between columns in the database and properties of a persistent class.   The <mapped-statement> can then simply define the SQL queries necessary to execute the needed functionality, and the map handles creation of the resultant Java object.   In addition to the Bike version above, your application currently also requires a map for Customer and Reservation.
<result-map>部分提供了數(shù)據(jù)庫(kù)字段與持久化類屬性之間的一顯式映射。<mapped-statement>接著可以簡(jiǎn)單定義運(yùn)行所需功能的必要的SQL查詢,而映射負(fù)責(zé)創(chuàng)建合成的Java 對(duì)象。除了上述的Bike 版本之外,你的應(yīng)用程序目前也需要一個(gè)關(guān)于Customer 和Reservation的映射。

你將不得不做一些OR框架通常為我們所做的活,如創(chuàng)建標(biāo)識(shí)符。在此例中,你將使用MySQL生成的序列(就是數(shù)據(jù)庫(kù)表中的那些AUTO_INCREMENT字段)。你只需在數(shù)據(jù)庫(kù)表定義時(shí)簡(jiǎn)單地把bikeId標(biāo)為AUTO_INCREMENT,這樣當(dāng)增加一條新記錄時(shí),你就可以在SQL語(yǔ)句中略過(guò)bikeId字段。我們映射中SaveBike語(yǔ)句就成了示例5-5。

示例5-5. Bike.xml
     <mapped-statement name="saveBike" >
         insert into bikes
         (manufacturer, model, frame, serialNo, weight, status)
         values(#manufacturer#, #model#, #frame#, #serialNo#, #weight#,
         #status#)
     </mapped-statement>


若你是在使用Oracle, Spring和iBATIS也支持Oracle生成的序列。

下一步,你可以更新應(yīng)用上下文,且需要列出我們的新fa&ccedil;ade,而fa&ccedil;ade要有SQL映射。把SQL 引入PROPERTIES 文件,就象我們對(duì)待JDBC 的參數(shù)一樣。 此外,你還需要配置事務(wù)策略。( 示例5-6)

示例5-6. .RentABikeApp-servlet.xml
<beans>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost/bikestore</value>
</property>
<property name="username">
<value>bikestore</value>
</property>
</bean>
<bean id="rentaBike" class="com.springbook.IBatisRentABike">
<property name="storeName"><value>Bruce‘s Bikes</value></property>
<property name="dataSource"><ref local="dataSource"/></property>
<property name="sqlMap"><ref local="sqlMap"/></property>
</bean>
<bean id="sqlMap"
class="org.springframework.orm.ibatis.SqlMapFactoryBean">
<property name="configLocation">
<value>/WEB-INF/ibatis.config</value>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource"><ref local="dataSource"/></property>
</bean>


這個(gè)事務(wù)策略就在應(yīng)用上下文中,你不必來(lái)管理提交適宜,因?yàn)镾pring 會(huì)為你完成。你將在第六章中更完整地探討事務(wù)策略。                                                

示例5-7. . ibatis.config
<?xml version="1.0" encoding="UTF-8"?>

<sql-map-config>
<sql-map resource="Bike.xml" />
<sql-map resource="Customer.xml" />
<sql-map resource="Reservation.xml" />
</sql-map-config>


稍后我們會(huì)談到事務(wù)策略。

發(fā)生了什么事?

你沒看到OR映射。OR框架會(huì)有意地將一個(gè)數(shù)據(jù)庫(kù)表與一個(gè)類或多個(gè)類關(guān)連起來(lái)。在此例中,iBATIS會(huì)將查詢結(jié)果賦予一個(gè)類。這意味著iBATIS并未試圖對(duì)你隱藏SQL細(xì)節(jié)。實(shí)際上,它是在擁抱SQL。

Spring打算通過(guò)模板來(lái)簡(jiǎn)化iBATIS的使用。iBATIS模板會(huì)給出類似JDBC模板的使用模型,你只需指定數(shù)據(jù)源和iBATIS映射的SQL語(yǔ)句。

當(dāng)執(zhí)行SQL語(yǔ)句時(shí),Spring與iBATIS一起為你管理資源,并按要求來(lái)創(chuàng)建和關(guān)閉連接。Spring會(huì)把映射的SQL語(yǔ)句傳給iBATIS, 由iBATIS來(lái)運(yùn)行映射的語(yǔ)句,且若需要,iBATIS會(huì)把結(jié)果集傳給給你映射SQL語(yǔ)句時(shí)所指定的Bean。如果你已有了任何參數(shù),那就可將那些結(jié)果集放入hash map中并把結(jié)果集傳給帶有映射的SQL語(yǔ)句的模板。

然而,從內(nèi)部所表現(xiàn)的來(lái)看,iBATIS或許并不象是一個(gè)OR框架,但使用模型的確有OR的趨向。 構(gòu)建帶有操作數(shù)據(jù)存儲(chǔ)的數(shù)據(jù)訪問對(duì)象(data access object),你不會(huì)在代碼中看到SQL語(yǔ)句,因?yàn)樗驯槐4嬖谂渲梦募辛耍襥BATIS使用對(duì)象集合而不是結(jié)果集。簡(jiǎn)而言之,這是在全部OR與JDBC之間的一個(gè)幽雅的折衷。

關(guān)于…

一切都適合iBATIS嗎? 由于這種使用模型與OR模型是那么的相似,且許多應(yīng)用對(duì)他們可能生成的SQL需要有更多的控制,或許你傾向于普遍地使用iBATIS。盡管如此,象JDO和Hibernate的OR框架仍擁有著屬于自己的舞臺(tái)。OR框架給了你更多的靈活性和更強(qiáng)大的功能:
·一些高級(jí)的對(duì)象模型導(dǎo)致了非常復(fù)雜的SQL,把這些復(fù)雜的SQL交由ORM來(lái)完成是最好的處理方式。 例如,繼承通常使得原始的JDBC API操作變得更為復(fù)雜。
·一些高級(jí)的性能特征,象延遲加載和數(shù)據(jù)抓取群組,要求對(duì)有效地的自動(dòng)控制需要一個(gè)更正式的模型。然而,完美地優(yōu)化后的JDBC至少要和ORM一樣快速。相對(duì)于使用原始的JDBC而言,由ORM提供的性能優(yōu)化選項(xiàng)對(duì)某些類型的問題更獲得較佳性能。
·ORM使某些問題變得更加有趣。操作對(duì)象比創(chuàng)建一套的SQL查詢更加簡(jiǎn)易。ORM很適合帶有簡(jiǎn)單的查找,創(chuàng)建,更新,根據(jù)主鍵讀取數(shù)據(jù)庫(kù)中的數(shù)據(jù)以及刪除記錄的應(yīng)用。

如若你的應(yīng)用有快速的數(shù)據(jù)模型和對(duì)象模型的變更,iBATIS就會(huì)很適合。如果你有了CRUD類型的應(yīng)用,那么,使用iBATIS可能就會(huì)有點(diǎn)乏味。相反地,如果你正尋找一種好的SQL訪問方式及在ORM和原始的JDBC間有效的折衷,那么,iBATIS可能就會(huì)給了你所需的一切。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多