日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iBATIS In Action:使用高级查询技术(一)

發布時間:2025/3/21 编程问答 10 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iBATIS In Action:使用高级查询技术(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
可以考慮根據對象的關系(關聯)來定義數據模型,然后使用iBATIS將它們一起加載。例如,如果在數據庫中,Account記錄對應著相關的Order記錄,而Order又對應著相關的OrderItem記錄,可以為這些記錄建立關系,當我們請求一條Account記錄時,可以一并獲取所有的OrderOrderItem記錄。下面的代碼清單顯示了如何定義我們的SQL映射:

<resultMap?id="ResultAccountInfoMap"?class="AccountInfo">
????
<result?property="accountId"
????column
="accountId"?/>
????
<result?property="orderList"?
????select
="Ch6.getOrderInfoList"
????column
="accountId"?/>
</resultMap>
<resultMap?id="ResultOrderInfoMap"?class="OrderInfo">
????
<result?property="orderId"?column="orderId"?/>
????
<result?property="orderItemList"?column="orderId"
????select
="Ch6.getOrderItemList"?/>
</resultMap>
<resultMap?id="ResultOrderItemMap"?class="OrderItem">
????
<result?property="orderId"?column="orderId"?/>
????
<result?property="orderItemId"?column="orderItemId"?/>
</resultMap>

<select?id="getAccountInfoList"?resultMap="ResultAccountInfoMap"?>
????select?accountId?from?Account
</select>
<select?id="getOrderInfoList"?resultMap="ResultOrderInfoMap">
????select?orderId?from?orders
????where?accountId?=?#value#
</select>
<select?id="getOrderItemList"?resultMap="ResultOrderItemMap">
????select?orderId,?orderItemId?from?orderItem
????where?orderid?=?#value#
</select>

先來看看結果映射(result map,即上面的ResultAccountInfoMapResultOrderInfoMapResultOrderItemMap),前兩個Map都用到了select特性。這個特性告訴iBATIS,屬性的值將由另一個映射語句來設置,語句的名稱就是select特性的值。例如,我們執行getAccountInfoList語句時,ResultAccountInfoMap結果映射有一個子元素:

<resultproperty="orderList"?select="Ch6.getOrderInfoList"?column="accountId"?/>

它的作用是告訴iBATIS,account對象的orderList屬性的值由Ch6.getOrderInfoList語句來設置,同時把accountId列的值傳給Ch6.getOrderInfoList作為參數。類似地,在設置order對象的orderItemList對象時,也會執行getOrderItemList語句。

這個功能給我們帶來便利的同時,也帶來了兩個問題。首先,創建包含大量對象的列表可能會消耗大量的內存。其次,這種方法會導致數據庫的I/O問題,其原因是所謂的“N+1 Select”現象,這個現象將在后面討論。對于每個問題,iBATIS框架都提供了解決方案,但是注意,沒有哪一種能同時解決這兩個問題

數據庫I/O

數據庫I/O是數據庫使用狀況的一項指標,也是數據庫性能的主要瓶頸之一。在讀取或寫入數據庫時,數據必須要經歷從磁盤到內存或者從內存到磁盤的轉換,這個過程是比較耗時的。在程序中使用緩存可以減少對數據庫的訪問,但這種方法使用時要謹慎,否則也會引發問題。要了解iBATIS中的緩存機制,可以參看第10章的內容。

在使用關聯數據時,可能會遭遇數據庫I/O問題。考慮一下這個場景:有1000Account,每一個關聯了1000Order,而每個Order則包含25OrderItem。如果嘗試將所有這些數據加載到內存,執行的SQL語句要超過1000000行(1條用來查詢Account1000條用于Order1000000條用于OrderItem),而創建的對象大約為2500萬——如果你真敢這么做,等你的系統管理員收拾你吧。

分析N1查詢問題

N1查詢問題是由于試圖加載多個父記錄(比如Account)的子記錄(Order)而引起的。因此,在查詢父記錄時,只需要1條語句,假設返回N條記錄,那么就需要再執行N條語句來查詢子記錄,引發所謂的“N1查詢”。

這些問題的解決方案

延遲加載(Lazy load,在6.2.2中詳細講述)可以解決一部分內存問題,它將加載過程打散為一些更小的過程。但是,它并沒有解決數據庫I/O問題,在最壞的情況下,它對數據庫的訪問次數與非延遲加載的版本是一樣的,因為加載數據時它的方法還是N1查詢(這個我們將在6.2.3中解決)。另一方面,當我們解決了N1查詢問題,減少了對數據庫的訪問,但我們的查詢結果卻包含著2500萬行記錄!

要決定是否使用復雜屬性,我們需要理解數據庫以及應用程序對數據庫的使用方式。如果您使用了本節中的技術,那可以省不少事兒,但如果誤用了它,也會有大麻煩。在接下來的兩節中,我們會分析如何根據目標選擇合適的策略。

讓我們從這個問題開始:像上面例子那樣將Account關聯到Order并將Order關聯到OrderItem是否合適?實際上,不是——order-to-orderitem關系是固定的,但是account-to-order關系則是不必要的。

我們是如是推理的:沒有所屬的OrderOrderItem是沒有意義的,而Account則是有意義的。一般情況下,沒有OrderItemOrder沒什么大用,相對的,不屬于任何OrderOrderItem是沒有意義的。另一方面,一個Account則可以認為是一個完整的對象。

但在我們的例子中,這種關系可以良好地描述相關的技術,因此我們會在一段時間內一直使用它。

6.2.2?延遲加載(Lazy loading

首先來看看延遲加載。如果不是對所有數據都馬上用到,那么延遲加載是有用的。例如,我們的程序首先在一個網頁顯示所有Account,然后銷售代理(我們的客戶)可以點擊一個Account來查看該AccountOrder列表,然后可以再點擊一個Order來查看其所有的OrderItem信息。在這種情況下,每次都僅查詢一個列表。這是對延遲加載的合理使用。

譯注:在iBATISJava版本中,使用延遲加載前還需要進行配置SqlMapConfig.xml以打開該功能。.NET版本中不需要配置等價的sqlMap.config

使用了延遲加載后,我們就可以更合理地進行對象創建和對數據庫的訪問。(還是使用上面的例子)如果一個用戶關注到OrderItem層次的數據,我們需要進行三次查詢(一次是為Account,一次是Order,還有一次是OrderItem),應用程序則要創建2025個對象(1000Account?1000Order25OrderItem)。效果明顯!而我們要做的僅僅是修改XML配置文件的一個特性(attribute)而已,無需改動代碼。

在一項不太嚴謹的測試中,我們發現,對于同樣的對象關聯關系(如上面的Account- Order- ORderItem),在加載第一個列表數據時(Account列表),沒有使用延遲加載的版本花費的時間是使用了延遲加載的版本的三倍。但是,在加載所有數據時,延遲加載的版本的時間卻多了20%。很明顯,我們要根據數據加載的數量和時機來確定是否采用延遲加載。此時,經驗是最重要的。

而有時您并不希望推遲數據的加載,而是希望在第一次請求的時候加載所有的數據。在這種情況下,您可以使用下節中的技術,它僅需要一次查詢即可。下節的方法避免了“N1查詢”。

6.2.3?避免“N1查詢”問題

我們來考慮如何避免“N1查詢”問題,這里可以使用連接語句(Join)。

這里用到的技術同前面類似。簡單的說,使用Result Map來定義對象間的關系,將頂層的Result Map關聯到映射語句。下面的例子的Data Map文件結構與前面大體一致,但是只需要執行一條SQL語句。

這里面有三個Result Map,一是關于Account的,二是關于Order的,三是OrderItem的。

關于AccountResult Map有兩個作用:

  • ?映射Account對象本身的屬性。
  • 告訴iBATIS如何映射下一層的關聯對象,這里是orderList

OrderResult Map作用與之類似。

  • 映射Order對象本身的屬性。
  • 告訴iBATIS如何映射下一層的關聯對象,這里是orderItemList
<resultMap?id="ResultAccountInfoNMap"?class="AccountInfo">
????
<result?property="account.accountId"?column="accountId"?/>
????
<result?property="orderList"?resultMapping="Ch6.ResultOrderInfoNMap"?/>
</resultMap>
<resultMap?id="ResultOrderInfoNMap"?class="OrderInfo">
????
<result?property="order.orderId"?column="orderId"?/>
????
<result?property="orderItemList"?resultMapping="Ch6.ResultOrderItemNMap"?/>
</resultMap>
<resultMap?id="ResultOrderItemNMap"?class="OrderItem">
????
<result?property="orderId"?column="orderId"?/>
????
<result?property="orderItemId"?column="orderItemId"?/>
</resultMap>

<select?id="getAccountInfoListN"?resultMap="ResultAccountInfoNMap">
????select?account.accountId?as?accountid,
????orders.orderid?as?orderid,
????orderitem.orderitemid?as?orderitemid
????from?account
????inner?join?orders?on?account.accountId?=?orders.accountId
????inner?join?orderitem?on?orders.orderId?=?orderitem.orderId
????order?by?accountId,?orderid,?orderitemid
</select>
我們的不太科學的測試表明,在加載少量數據時,該方法將原先方法的性能提高為71。我們猜想,對于例子中使用的2500萬條數據,兩種方法仍然不錯。

譯注:在iBATIS.NET DataMapper 1.6.1中,添加了groupBy特性,它將進一步改善性能。詳細內容請參看相關文檔,本文使用的是DataMapper 1.5.1

需要注意的是,盡管性能得到改善,內存的消耗仍然與沒有使用延遲加載的版本相同。所有的記錄一起放入內存,因此盡管它稍微快了一點,但內存的消耗仍是問題。

譯注:在加載復雜屬性時可能出現兩方面的問題,一是對數據庫的訪問,二是創建對象時對內存的消耗。我們可以采用延遲加載或Join的方法來解決這些問題,但是兩者都不是萬靈藥。延遲加載的原理時推遲對復雜屬性的加載,以減少對數據庫的訪問和對象的創建,但它的前提是復雜屬性不會馬上用到,否則的話,延遲就失去意義。Join的原理是通過一條SQL語句加載所有數據,這樣可以大幅度減少對數據庫的訪問量,它的前提是對象的數量不會太多。該如何選擇呢?下面的表格給出了簡單的原則:

延遲加載

Join

如果要加載大量的數據,它們不會馬上用到,延遲加載會比較合適。

數據量較小或者數據馬上就會用到,Join方法比較合適。

譯注:另外,我覺得還有一條很重要的原則,那就是永遠只加載必需的數據。以上面的例子來說,我們不太可能會同時顯示1000Account給用戶看,這時就不要同時加載1000Account的數據了,可以通過分頁只顯示50條數據,在此基礎上再應用延遲加載或Join效果會很不錯。關于在Web項目中如何使用iBATIS進行分頁,請參看這篇文章

好了,這些就是復雜屬性映射相關的內容。下一篇中,我們將會了解iBATIS的其它用法。

上一篇:iBATIS In Action:執行非查詢語句(二)

下一篇:iBATIS In Action:使用高級查詢技術(二)


本文轉自一個程序員的自省博客園博客,原文鏈接:http://www.cnblogs.com/anderslly/archive/2007/12/27/ibatisinactionch062.html,如需轉載請自行聯系原作者。

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的iBATIS In Action:使用高级查询技术(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 操操干干 | 亚洲精品视频三区 | 国产情侣小视频 | av一级网站 | 亚洲国产成人一区二区 | 国产日韩精品一区 | 少妇高潮一区二区三区99刮毛 | 成人片片| 吻胸摸激情床激烈视频大胸 | 日本天堂在线视频 | 秋霞福利网 | 亚洲午夜在线观看 | 香蕉视频911 | 青青青手机在线视频 | 五月天激情丁香 | 中文字幕日韩精品在线观看 | 99艹| 中文在线永久免费观看 | 久久国产一区二区三区 | 美女扒开内裤让男人捅 | 亚洲精品在线网站 | 国产亚洲不卡 | 国产一区二 | 91成人免费电影 | a√天堂资源 | 九色蝌蚪9l视频蝌蚪9l视频 | 亚洲午夜福利一区二区三区 | 日本囗交做爰视频 | 9999免费视频 | 国产亚洲精品久久久久动 | 少妇紧身牛仔裤裤啪啪 | 日韩成人午夜影院 | 欧美色哟哟 | 亚洲女人毛茸茸 | 日本精品二区 | avtt2015 | 特级毛片爽www免费版 | 草草久久久 | 亚洲综合另类小说 | 久久精品国产亚洲AV高清综合 | 大陆av片 | 中国黄色三级 | 国产精品探花视频 | 人体内射精一区二区三区 | 日韩精品极品视频 | 久久乐av| 伊人春色在线视频 | 国产一线二线在线观看 | 国产黑丝在线播放 | 91精品国产综合久久香蕉 | 秋霞成人午夜伦在线观看 | 国产精品三区四区 | 久操视频精品 | 成人欧美精品一区二区 | 久久久久亚洲色欲AV无码网站 | 黄色一级大片 | 午夜资源站 | 色啪综合 | 精品久久香蕉国产线看观看亚洲 | 免费在线看黄视频 | 日本电影成人 | www.avcao| 久久性网 | 欧美aa在线观看 | 欧美日韩成人免费 | 天天视频污| 国产一级视频免费观看 | 国产在线观看免费 | 好逼天天操| 日本精品视频一区 | 日韩一区二区免费看 | 久久草av | 成人国产精品久久久网站 | 91精品人妻一区二区三区蜜桃2 | 国产高清www| 一女二男一黄一片 | 欧美日韩首页 | av收藏小四郎最新地址 | 欧美一区二区在线看 | 欧美激情在线狂野欧美精品 | 成人超碰在线 | 成年人www| 一区二区视频免费看 | 久久久精品中文字幕麻豆发布 | 午夜福利123 | 国产黄色三级网站 | 欧美三极片| 欧美黑人三级 | 欧美激情亚洲 | 自拍偷拍视频在线 | 中文字幕在线免费观看视频 | 国产精品久久久亚洲 | 欧美午夜精品 | 性大毛片视频 | 日日夜夜免费视频 | 97在线播放免费观看 | 99国产精品久久久久99打野战 | 修女也疯狂3免费观看完整版 | 99国产精品国产免费观看 |