成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

iBATIS使用之高級(jí)查詢技術(shù)詳解

開發(fā) 后端
iBATIS使用之高級(jí)查詢技術(shù)iBATIS 是In Action之高級(jí)查詢技術(shù)的展現(xiàn),那么本文就向你展示這項(xiàng)技術(shù)的內(nèi)涵。

iBATIS In Action為iBATIS展現(xiàn)自己強(qiáng)大功能提供了保證,iBATIS也可以完成更為復(fù)雜的任務(wù)。在本章中,我們會(huì)了解新的技術(shù),減少我們的編碼量;以及改善性能、降低資源消耗(footprint)的幾種方法。

1 使用iBATIS操作XML

譯者注:iBATIS的Java版本可以操作基于XML的數(shù)據(jù)。但意義并不是很大,在以后的版本中該特性可能會(huì)被移除。iBATIS.NET則未提供該功能。

2 使用映射語句關(guān)聯(lián)對(duì)象

iBATIS框架也提供了多種方法用以關(guān)聯(lián)復(fù)雜的對(duì)象,比如訂單(order)和它的訂單項(xiàng)(order item)(還有它們的相關(guān)產(chǎn)品、顧客等等)。每種方法都有其優(yōu)點(diǎn)和缺點(diǎn),正所謂“尺有所短,寸有所長(zhǎng)”,每一種方案都不是完美的。應(yīng)根據(jù)需要來選擇適合的方案。

注意:為簡(jiǎn)短起見,在本章的余下的例子中,我們將省略那些對(duì)于演示來說不必要的數(shù)據(jù)。例如,當(dāng)我們獲取了一個(gè)顧客(customer)對(duì)象,我們不會(huì)獲取它的所有字段,而是僅僅獲取它的主鍵和外鍵。

2.1 復(fù)雜的集合屬性

在第4章中,我們學(xué)習(xí)了如何使用SELECT語句從數(shù)據(jù)庫(kù)獲取數(shù)據(jù)。在那些例子中,我們獲取的結(jié)果僅僅是單個(gè)對(duì)象,即使是連接多表也是如此。事實(shí)上,如果您有多個(gè)復(fù)雜對(duì)象,也可以使用iBATIS加載它們。

如果我們的應(yīng)用程序模型與數(shù)據(jù)模型比較類似,那么這個(gè)功能會(huì)很有用??梢钥紤]根據(jù)對(duì)象的關(guān)系(關(guān)聯(lián))來定義數(shù)據(jù)模型,然后使用iBATIS將它們一起加載。例如,如果在數(shù)據(jù)庫(kù)中,Account記錄對(duì)應(yīng)著相關(guān)的Order記錄,而Order又對(duì)應(yīng)著相關(guān)的OrderItem記錄,可以為這些記錄建立關(guān)系,當(dāng)我們請(qǐng)求一條Account記錄時(shí),可以一并獲取所有的Order和OrderItem記錄。下面的代碼清單顯示了如何定義我們的SQL映射:

SQL映射 

圖1SQL映射

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

select特性的值 

圖2select特性的值

它的作用是告訴iBATIS,account對(duì)象的orderList屬性的值由ChgetOrderInfoList語句來設(shè)置,同時(shí)把a(bǔ)ccountId列的值傳給ChgetOrderInfoList作為參數(shù)。類似地,在設(shè)置order對(duì)象的orderItemList對(duì)象時(shí),也會(huì)執(zhí)行g(shù)etOrderItemList語句。

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

數(shù)據(jù)庫(kù)I/O

數(shù)據(jù)庫(kù)I/O是數(shù)據(jù)庫(kù)使用狀況的一項(xiàng)指標(biāo),也是數(shù)據(jù)庫(kù)性能的主要瓶頸之一。在讀取或?qū)懭霐?shù)據(jù)庫(kù)時(shí),數(shù)據(jù)必須要經(jīng)歷從磁盤到內(nèi)存或者從內(nèi)存到磁盤的轉(zhuǎn)換,這個(gè)過程是比較耗時(shí)的。在程序中使用緩存可以減少對(duì)數(shù)據(jù)庫(kù)的訪問,但這種方法使用時(shí)要謹(jǐn)慎,否則也會(huì)引發(fā)問題。要了解iBATIS中的緩存機(jī)制,可以參看第10章的內(nèi)容。

在使用關(guān)聯(lián)數(shù)據(jù)時(shí),可能會(huì)遭遇數(shù)據(jù)庫(kù)I/O問題??紤]一下這個(gè)場(chǎng)景:有1000個(gè)Account,每一個(gè)關(guān)聯(lián)了1000個(gè)Order,而每個(gè)Order則包含25個(gè)OrderItem。如果嘗試將所有這些數(shù)據(jù)加載到內(nèi)存,執(zhí)行的SQL語句要超過1000000行(1條用來查詢Account,1000條用于Order,1000000條用于OrderItem),而創(chuàng)建的對(duì)象大約為2500萬——如果你真敢這么做,等你的系統(tǒng)管理員收拾你吧。

分析N+1查詢問題

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

這些問題的解決方案

延遲加載(Lazy load,在2.2中詳細(xì)講述)可以解決一部分內(nèi)存問題,它將加載過程打散為一些更小的過程。但是,它并沒有解決數(shù)據(jù)庫(kù)I/O問題,在最壞的情況下,它對(duì)數(shù)據(jù)庫(kù)的訪問次數(shù)與非延遲加載的版本是一樣的,因?yàn)榧虞d數(shù)據(jù)時(shí)它的方法還是N+1查詢(這個(gè)我們將在2.3中解決)。另一方面,當(dāng)我們解決了N+1查詢問題,減少了對(duì)數(shù)據(jù)庫(kù)的訪問,但我們的查詢結(jié)果卻包含著2500萬行記錄!

要決定是否使用復(fù)雜屬性,我們需要理解數(shù)據(jù)庫(kù)以及應(yīng)用程序?qū)?shù)據(jù)庫(kù)的使用方式。如果您使用了本節(jié)中的技術(shù),那可以省不少事兒,但如果誤用了它,也會(huì)有大麻煩。在接下來的兩節(jié)中,我們會(huì)分析如何根據(jù)目標(biāo)選擇合適的策略。

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

我們是如是推理的:沒有所屬的Order,OrderItem是沒有意義的,而Account則是有意義的。一般情況下,沒有OrderItem,Order沒什么大用,相對(duì)的,不屬于任何Order的OrderItem是沒有意義的。另一方面,一個(gè)Account則可以認(rèn)為是一個(gè)完整的對(duì)象。

但在我們的例子中,這種關(guān)系可以良好地描述相關(guān)的技術(shù),因此我們會(huì)在一段時(shí)間內(nèi)一直使用它。

2.2 延遲加載(Lazy loading)

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

譯注:在iBATIS的Java版本中,使用延遲加載前還需要進(jìn)行配置SqlMapConfig.xml以打開該功能。在.NET版本中不需要配置等價(jià)的sqlMap.config。

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

在一項(xiàng)不太嚴(yán)謹(jǐn)?shù)臏y(cè)試中,我們發(fā)現(xiàn),對(duì)于同樣的對(duì)象關(guān)聯(lián)關(guān)系(如上面的Account- Order- ORderItem),在加載第一個(gè)列表數(shù)據(jù)時(shí)(Account列表),沒有使用延遲加載的版本花費(fèi)的時(shí)間是使用了延遲加載的版本的三倍。但是,在加載所有數(shù)據(jù)時(shí),延遲加載的版本的時(shí)間卻多了20%。很明顯,我們要根據(jù)數(shù)據(jù)加載的數(shù)量和時(shí)機(jī)來確定是否采用延遲加載。此時(shí),經(jīng)驗(yàn)是最重要的。

而有時(shí)您并不希望推遲數(shù)據(jù)的加載,而是希望在第一次請(qǐng)求的時(shí)候加載所有的數(shù)據(jù)。在這種情況下,您可以使用下節(jié)中的技術(shù),它僅需要一次查詢即可。下節(jié)的方法避免了“N+1查詢”。

2.3 避免“N+1查詢”問題

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

這里用到的技術(shù)同前面類似。簡(jiǎn)單的說,使用Result Map來定義對(duì)象間的關(guān)系,將頂層的Result Map關(guān)聯(lián)到映射語句。下面的例子的Data Map文件結(jié)構(gòu)與前面大體一致,但是只需要執(zhí)行一條SQL語句。

這里面有三個(gè)Result Map,一是關(guān)于Account的,二是關(guān)于Order的,三是OrderItem的。

關(guān)于Account的Result Map有兩個(gè)作用:

映射Account對(duì)象本身的屬性。

告訴iBATIS如何映射下一層的關(guān)聯(lián)對(duì)象,這里是orderList。

Order的Result Map作用與之類似。

映射Order對(duì)象本身的屬性。

告訴iBATIS如何映射下一層的關(guān)聯(lián)對(duì)象,這里是orderItemList。

orderItemList 

圖3orderItemList

我們的不太科學(xué)的測(cè)試表明,在加載少量數(shù)據(jù)時(shí),該方法將原先方法的性能提高為7:1。我們猜想,對(duì)于例子中使用的2500萬條數(shù)據(jù),兩種方法仍然不錯(cuò)。

譯注:在iBATIS.NET DataMapper 1.1中,添加了groupBy特性,它將進(jìn)一步改善性能。詳細(xì)內(nèi)容請(qǐng)參看相關(guān)文檔,本文使用的是DataMapper 1.5.1。

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

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

簡(jiǎn)單的原則 

圖4簡(jiǎn)單的原則

譯注:另外,我覺得還有一條很重要的原則,那就是永遠(yuǎn)只加載必需的數(shù)據(jù)。以上面的例子來說,我們不太可能會(huì)同時(shí)顯示1000個(gè)Account給用戶看,這時(shí)就不要同時(shí)加載1000個(gè)Account的數(shù)據(jù)了,可以通過分頁(yè)只顯示50條數(shù)據(jù),在此基礎(chǔ)上再應(yīng)用延遲加載或Join效果會(huì)很不錯(cuò)。關(guān)于在Web項(xiàng)目中如何使用iBATIS進(jìn)行分頁(yè),請(qǐng)參看這篇文章。

關(guān)于iBATIS使用的相關(guān)以及復(fù)雜屬性映射相關(guān)的內(nèi)容就介紹到這里,希望對(duì)你有所幫助。

【編輯推薦】

  1. iBATIS是什么?
  2. iBATIS的優(yōu)、缺點(diǎn)及注意事項(xiàng)淺談
  3. iBATIS不適合使用的四種情況淺析
  4. iBATIS發(fā)展方向的四方面淺析
  5. iBATIS快速創(chuàng)建應(yīng)用淺析
責(zé)任編輯:仲衡 來源: 互聯(lián)網(wǎng)
相關(guān)推薦

2010-05-27 17:57:09

Svn使用入門

2015-05-04 14:51:49

SQL子查詢

2011-08-12 09:30:04

SQL Server數(shù)高級(jí)SQL查詢

2022-01-12 08:10:40

APISIXIngress Url Rewrite

2009-07-15 11:43:13

<iterate>標(biāo)簽

2022-02-23 21:10:53

LonghornKubernetes快照

2011-04-19 09:14:59

Ibatis

2009-08-11 13:20:45

高斯消元法C#算法

2009-07-17 17:57:20

NPetShop iBATIS.Net

2009-07-15 13:11:25

ibatis動(dòng)態(tài)查詢

2023-06-12 08:30:08

多線程編程線程調(diào)試

2009-07-22 10:42:59

iBATIS Cach

2014-03-12 10:33:56

GitTortoiseGit

2009-07-22 13:04:41

iBATIS動(dòng)態(tài)查詢

2009-07-24 16:59:57

iBatis模糊查詢

2009-07-22 16:13:40

iBATIS用法SqlMapTempl

2023-11-06 12:00:04

GORM

2009-11-05 15:47:37

CCNP學(xué)習(xí)筆記

2009-07-21 17:06:35

iBATIS.NET執(zhí)

2013-01-30 15:36:03

NFC移動(dòng)支付藍(lán)牙
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产黄色av电影 | 一区二区三区欧美在线 | 超碰在线人 | 欧美黄在线观看 | a级毛片免费高清视频 | 日韩欧美精品在线播放 | 国产成人免费视频网站高清观看视频 | 欧美日韩综合视频 | 四季久久免费一区二区三区四区 | 欧美一区在线视频 | 亚洲视频一区二区三区 | 中文字幕视频在线观看 | 中文av电影 | 欧美日韩久久 | 欧美一区二区三区在线观看 | 久久久久久国产精品久久 | 亚洲在线中文字幕 | 久久aⅴ乱码一区二区三区 亚洲欧美综合精品另类天天更新 | 久久久精品综合 | 成人午夜av| 在线观看av网站永久 | 天天操夜夜艹 | wwwww在线观看 | 国产精品欧美一区二区三区 | 国产精品国产精品国产专区不片 | 麻豆久久久久 | 亚洲视频在线一区 | 久久久久久久av | 久久精品欧美视频 | 日韩欧美成人精品 | 精品久久久久久亚洲综合网 | 97精品超碰一区二区三区 | 99久久精品国产麻豆演员表 | 国产福利二区 | 午夜国产一级片 | 国产免费一区二区三区网站免费 | 国产资源在线视频 | 亚洲午夜视频在线观看 | 超碰欧美 | 日韩一二三区视频 | 日本久久久久久 |