Open-Open

          皇家撒拉哥薩
          posts - 32, comments - 3, trackbacks - 0, articles - 1

          Spring與iBATIS的集成

          Posted on 2006-05-20 00:14 開源愛好者 閱讀(582) 評論(0)  編輯  收藏 所屬分類: iBATIS
          iBATIS似乎已遠離眾說紛紜的OR框架之列,通常人們對非常流行的Hibernate情有獨鐘。但正如Spring: A Developer's Notebook作者Bruce Tate 和Justin Gehtland所說的那樣,與其他的OR框架相比,iBATIS獨辟蹊徑:“iBATIS不是試圖從根本上掩蓋SQL,實際上,它是在擁抱SQL。”

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

          就象Developer's Notebook 系列中所有的書一樣,你將由直接的且實用的方式獲得信息,這些信息包含了完成你工作所需的細節。換言之:“一切來自實戰,沒有講義。”

          作者:czyczy
          原文:http://www.matrix.org.cn/resource/article/44/44304_Spring+iBATIS.html
          關鍵字:Spring;iBATIS

          對象關系持久化(OR Persistence)

          本章所涉及的內容為:
          · 與iBATIS的集成
          · 在Spring的應用中使用JDO
          · 在Spring的應用中使用Hibernate
          · 運行測試用例


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

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

          ·iBATIS 是一種JDBC助手類框架,它給了你一些OR映射及使用OR的好處,但不帶 有太多的風險。
          ·JDO是一種飽受爭議的持久化標準,但它有著一些獨特的實現,這使得JDO在行業中也算得上是最完美的持久化框架之一。
          ·Hibernate 是在JBoss組織控制下的一開源持久化框架。它可能是時下最為流行的持久化框架。大量的客戶采用它,而且客戶的數量還在持續穩定地增長。????????

          在本章中,我們會對所提的三個框架進行嘗試,而不必對應用的其余部分的代碼做任何變更。

          與iBATIS集成

          常言道:“樹大招風”。在大肆宣揚的J2EE和.Net之爭中, Sun的一示例應用程序被用來作為衡量應用服務器在運行時的各項性能的核心基準。 .Net非常好地打敗了基于EJB的J2EE版本, 且方興未艾。Clinton Begin 開發了iBATIS的持久化框架,他在iBATIS中使用PetStore的簡化版,且自從那以后iBATIS就越來越流行。Spring提供非常優良的與iBATIS的集成功能, 在此章中將對其進行介紹。

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

          然而,我不想扯得太遠。嘗試一下象iBATIS SqlMaps的框架給了你OR的使用模型又何嘗不可呢?當然,我們不會強迫你一口吞下一只大象。具體來說,iBATIS讓你:
          ·映射字段和SQL語句到關鍵字
          ·使用SQL的全部功能而沒有乏味的JDBC
          ·從你的代碼中剝離SQL
          Spring 與iBATIS的集成給了你這些及更多的裨益, 讓我們為此而忙乎起來。

          我該怎么做?


          首先,你需要安裝iBATIS。由于iBATIS的配置會在你的Spring 應用上下文中完成,因此你不需要立即配置它。在http://www.ibatis.com/(譯注:最新的網址為:http://ibatis.apache.org/,iBATIS已于2004-08-16并入Apache 軟件基金會)上可以下載并安裝。在本書中我們使用1.3.1版本。把iBATIS提供的jars(ibatis-sqlmap.jar, ibatis-dao.jar, and ibatis-common.jar)和Spring提供的jdom.jar(在Spring的/lib 目錄下)放到你的項目目錄/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.
          你已經有了門戶(façade)和模型(model)的接口,因而你需要facade和SQL語句的實現。首先,你可以象示例5-1那樣,在你的應用中實現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將每一查詢分成一個獨立的映射,那樣你就可以用名字來執行查詢。

          SqlMapTemplate由Spring的SqlMapDaoSupport 類提供,我們的RentABike實現必須來繼承這個類。SqlMapTemplate負責建立和管理底層數據存儲的連接,同時也解釋了你所提供的映射文件。你可以把template 看成是你對于iBATIS命名式查詢所做那些事情的默認實現。

          你也需要創建SQL語句,可以給每條SQL語句取一個名字。然后,把結果映射給Java Bean。在這里你有兩種選擇,你可以在SQL中把每個Bean屬性作為別名來引用,或在查詢和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>部分提供了數據庫字段與持久化類屬性之間的一顯式映射。<mapped-statement>接著可以簡單定義運行所需功能的必要的SQL查詢,而映射負責創建合成的Java 對象。除了上述的Bike 版本之外,你的應用程序目前也需要一個關于Customer 和Reservation的映射。

          你將不得不做一些OR框架通常為我們所做的活,如創建標識符。在此例中,你將使用MySQL生成的序列(就是數據庫表中的那些AUTO_INCREMENT字段)。你只需在數據庫表定義時簡單地把bikeId標為AUTO_INCREMENT,這樣當增加一條新記錄時,你就可以在SQL語句中略過bikeId字段。我們映射中SaveBike語句就成了示例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生成的序列。

          下一步,你可以更新應用上下文,且需要列出我們的新fa&ccedil;ade,而fa&ccedil;ade要有SQL映射。把SQL 引入PROPERTIES 文件,就象我們對待JDBC 的參數一樣。 此外,你還需要配置事務策略。( 示例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>


          這個事務策略就在應用上下文中,你不必來管理提交適宜,因為Spring 會為你完成。你將在第六章中更完整地探討事務策略。????????????????????????????????????????????????

          示例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>


          稍后我們會談到事務策略。

          發生了什么事?

          你沒看到OR映射。OR框架會有意地將一個數據庫表與一個類或多個類關連起來。在此例中,iBATIS會將查詢結果賦予一個類。這意味著iBATIS并未試圖對你隱藏SQL細節。實際上,它是在擁抱SQL。

          Spring打算通過模板來簡化iBATIS的使用。iBATIS模板會給出類似JDBC模板的使用模型,你只需指定數據源和iBATIS映射的SQL語句。

          當執行SQL語句時,Spring與iBATIS一起為你管理資源,并按要求來創建和關閉連接。Spring會把映射的SQL語句傳給iBATIS, 由iBATIS來運行映射的語句,且若需要,iBATIS會把結果集傳給給你映射SQL語句時所指定的Bean。如果你已有了任何參數,那就可將那些結果集放入hash map中并把結果集傳給帶有映射的SQL語句的模板。

          然而,從內部所表現的來看,iBATIS或許并不象是一個OR框架,但使用模型的確有OR的趨向。 構建帶有操作數據存儲的數據訪問對象(data access object),你不會在代碼中看到SQL語句,因為它已被保存在配置文件中了,且iBATIS使用對象集合而不是結果集。簡而言之,這是在全部OR與JDBC之間的一個幽雅的折衷。

          關于…

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

          如若你的應用有快速的數據模型和對象模型的變更,iBATIS就會很適合。如果你有了CRUD類型的應用,那么,使用iBATIS可能就會有點乏味。相反地,如果你正尋找一種好的SQL訪問方式及在ORM和原始的JDBC間有效的折衷,那么,iBATIS可能就會給了你所需的一切。
          主站蜘蛛池模板: 大英县| 福鼎市| 樟树市| 惠水县| 尖扎县| 安庆市| 富宁县| 手游| 时尚| 三江| 河曲县| 阜南县| 峡江县| 南昌县| 崇明县| 绥中县| 宜兰市| 赤水市| 益阳市| 贵溪市| 四子王旗| 南涧| 郑州市| 永泰县| 永善县| 禹州市| 博湖县| 平和县| 普洱| 全南县| 德令哈市| 海阳市| 甘泉县| 高邑县| 文登市| 德兴市| 高州市| 平顶山市| 宝鸡市| 永寿县| 太保市|