<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 56, comments - 77, trackbacks - 0, articles - 1
      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    ORM問(wèn)題域

    Posted on 2009-12-28 23:49 切爾斯基 閱讀(1981) 評(píng)論(0)  編輯  收藏

    假設(shè)我們必須處理對(duì)象的存儲(chǔ), 加載, 和查詢(xún). 性能和引用完整性的約束, 給接口的實(shí)現(xiàn)帶來(lái)了以下問(wèn)題:

    1. 加載根對(duì)象時(shí)如何避免加載大半個(gè)數(shù)據(jù)庫(kù)

    2. 存儲(chǔ)時(shí)如何更新整個(gè)對(duì)象圖

    3. 存儲(chǔ)時(shí)如何高效的更新整個(gè)對(duì)象圖

    4. 何時(shí)同步對(duì)象的內(nèi)存狀態(tài)和持久存儲(chǔ)狀態(tài)

    5. 如何確保在出錯(cuò)時(shí)保持對(duì)象內(nèi)存狀態(tài)和持久存儲(chǔ)狀態(tài)之間的一致性

    6. 如何保證引用的唯一性以避免可能的更新沖突

    對(duì)性能的精益求精, 又促使人們解決更多的細(xì)節(jié)問(wèn)題:

    1. N+1查詢(xún)問(wèn)題

    2. 分離查詢(xún)模型和存儲(chǔ)模型

    3. 盡量減少查詢(xún)語(yǔ)句

    這些問(wèn)題的解決方案又會(huì)帶來(lái)新的問(wèn)題.

     

    1. 加載根對(duì)象時(shí)如何避免加載大半個(gè)數(shù)據(jù)庫(kù)

    更多的時(shí)候這是一個(gè)建模問(wèn)題, 為什么我只需要顯示一點(diǎn)信息, 更新一點(diǎn)信息, 卻拉家?guī)Э诎寻藯U子打不著的親戚都帶上 : 細(xì)粒度對(duì)象設(shè)計(jì), 直接訪(fǎng)問(wèn)需要的信息, 減少所謂根對(duì)象的存在

    一個(gè)workaround是延遲加載, 當(dāng)你無(wú)法修復(fù)你錯(cuò)誤的建模時(shí), 當(dāng)真正去訪(fǎng)問(wèn)子對(duì)象的時(shí)候再發(fā)出查詢(xún)語(yǔ)句去加載. 這個(gè)方案會(huì)帶來(lái)如下問(wèn)題:

    1. 查詢(xún)語(yǔ)句較多. 無(wú)解, 延遲意味著至少兩條SQL語(yǔ)句, 只能盡量減少

    2. 延遲加載的時(shí)機(jī), 是自動(dòng)透明的延遲加載, 還是用戶(hù)確定何時(shí)加載

    Hibernate可通過(guò)配置文件指定是否lazy load, 一旦指定, 后面的load就是透明的在訪(fǎng)問(wèn)子對(duì)象時(shí)發(fā)生. 也可在發(fā)出每次查詢(xún)時(shí)顯式指定

    Entity Framework則要求用戶(hù)在每一次查詢(xún)時(shí)顯式指定包含哪個(gè)子對(duì)象, 對(duì)沒(méi)有指定包含的子對(duì)象, 只能在訪(fǎng)問(wèn)前顯示使用load(). 理由是決定加載不加載,何時(shí)加載都是程序員的責(zé)任

    1. 然而更大的問(wèn)題是如何管理數(shù)據(jù)庫(kù)連接, 要確保延遲加載的時(shí)候數(shù)據(jù)庫(kù)連接是開(kāi)著的

    可以使用Interceptor等技術(shù)維持 Session per request, Open Session in View pattern(處理好異常等, 確保session會(huì)關(guān)閉).

    能在一個(gè) Session 中使用兩個(gè)事務(wù)嗎?

    是的,這事實(shí)上是這種模式(Open Session In View)的一個(gè)更好的實(shí)現(xiàn)。在一個(gè)請(qǐng)求事件中,一個(gè)數(shù)據(jù)庫(kù)事務(wù)用于數(shù)據(jù)的讀寫(xiě)。第二個(gè)數(shù)據(jù)庫(kù)事務(wù)僅用于在渲染視圖期間讀數(shù)據(jù)。在這點(diǎn)上沒(méi)有對(duì)對(duì)象的修改。因此,數(shù)據(jù)庫(kù)鎖早在第一個(gè)事務(wù)時(shí)就被釋放了,這使得應(yīng)用有更好的可伸縮性,第二個(gè)事務(wù)可以被優(yōu)化。要使用兩階段的事務(wù),你需要比 Servlet Filter 更強(qiáng)大的攔截器 - AOP 是個(gè)很好的選擇。JBoss Seam 使用了這種模式。

    為什么 Hibernate 不在需要時(shí)就加載 Object?

    每個(gè)月很多人都會(huì)有這種想法,為什么 Hibernate 不能在有需要的就開(kāi)啟一個(gè)新的數(shù)據(jù)庫(kù)連接(更有效率的是開(kāi)啟一個(gè) Session),然后加載集合或是初始化代理,而是選擇拋出一個(gè) LazyInitializationException。當(dāng)然,這種想法,第一眼看上去可能是明智之舉。但這種做法有很多的缺點(diǎn),只有當(dāng)你考慮特別的事務(wù)訪(fǎng)問(wèn)時(shí)才會(huì)發(fā)現(xiàn)。

    如果 Hibernate 可以進(jìn)行任意的數(shù)據(jù)庫(kù)連接和事務(wù),這種操作是開(kāi)發(fā)人員不可知,并且也是在任何事務(wù)邊界之外的,那還要事務(wù)邊界做什么。當(dāng) Hibernate 開(kāi)啟了新的數(shù)據(jù)庫(kù)連接去加載集合,但同時(shí)集合的擁有者卻被刪除了,這是將會(huì)發(fā)生什么?(注意,這種情況是不會(huì)發(fā)生在上面提到的兩階段的事務(wù)模式中的 - 單個(gè) Session 可對(duì)實(shí)體可重復(fù)讀。)當(dāng)所有的對(duì)象都可以通過(guò)關(guān)聯(lián)導(dǎo)航獲取時(shí)為什么還要有 Service 層?這種方式將消耗多少內(nèi)存?哪些對(duì)象要首先被清除掉?所有這些問(wèn)題都是無(wú)解的,因?yàn)?Hibernate 是一個(gè)在線(xiàn)的事務(wù)處理服務(wù)(并包含一些批處理操作),并不是一個(gè)“在未定義的工作單元中從數(shù)據(jù)持久倉(cāng)庫(kù)取得對(duì)象”的服務(wù)。此外,對(duì)于 n+1 查詢(xún)問(wèn)題,我們是否需要 n+1 的事務(wù)和連接的問(wèn)題?

    這個(gè)問(wèn)題的解決方案當(dāng)然是正確的工作單元?jiǎng)澐趾驮O(shè)計(jì),支撐其的攔截技術(shù)就像這里所展現(xiàn)的一樣,并且/或者正確的抓取技術(shù),使得特定工作單元所需的全部信息能夠以最小的影響、最好的性能和伸縮性被獲得。

     

    2. 存儲(chǔ)時(shí)如何更新整個(gè)對(duì)象圖

    框架支持級(jí)聯(lián)更新. 是否應(yīng)該級(jí)聯(lián)更新, 哪些操作可以級(jí)聯(lián), 哪些不可以, 對(duì)象之間的哪些類(lèi)型的關(guān)聯(lián)可以級(jí)聯(lián), 哪些不可以, 則是程序員的責(zé)任

    • 通常被聚合的對(duì)象, 其生命周期應(yīng)由父對(duì)象負(fù)責(zé), 新增/更新/刪除都應(yīng)級(jí)聯(lián)

    • 自身有存在意義的實(shí)體, 可以級(jí)聯(lián)更新, 但不應(yīng)刪除和新增

     

    3. 存儲(chǔ)時(shí)如何高效的更新整個(gè)對(duì)象圖

    常用工作單元模式, Unit of Work.

     

    4. 何時(shí)同步對(duì)象的內(nèi)存狀態(tài)和持久存儲(chǔ)狀態(tài)

    任何改動(dòng)都立即提交到數(shù)據(jù)庫(kù)會(huì)帶來(lái)額外開(kāi)銷(xiāo). 一個(gè)時(shí)機(jī)是事務(wù)提交時(shí).

    Hibernate: 每間隔一段時(shí)間,Session會(huì)執(zhí)行一些必需的SQL語(yǔ)句來(lái)把內(nèi)存中的對(duì)象的狀態(tài)同步到JDBC連接中。這個(gè)過(guò)程被稱(chēng)為刷出(flush),默認(rèn)會(huì)在下面的時(shí)間點(diǎn)執(zhí)行:

    • 在某些查詢(xún)執(zhí)行之前

    • 在調(diào)用org.hibernate.Transaction.commit()的時(shí)候

    • 在調(diào)用Session.flush()的時(shí)候

     

    5. 如何確保在出錯(cuò)時(shí)保持對(duì)象內(nèi)存狀態(tài)和持久存儲(chǔ)狀態(tài)之間的一致性

    數(shù)據(jù)庫(kù)事務(wù)回滾, 清空內(nèi)存緩存, 重新加載

     

    6. 如何避免或處理可能的更新沖突

    保證引用的唯一性: 使用單一的加載入口和緩存, Identity Map.

    樂(lè)觀(guān)離線(xiàn)鎖會(huì)引入更新沖突問(wèn)題, 一般使用Versioning來(lái)解決, 類(lèi)似版本控制系統(tǒng)的更新問(wèn)題; 但業(yè)務(wù)對(duì)象很少能自動(dòng)Merge, Merge的語(yǔ)義也不好定義, 所以一般檢測(cè)到?jīng)_突之后只好重做了, 或者取決于業(yè)務(wù)邏輯, Last Win也是一種策略.

     

    7. N+1查詢(xún)問(wèn)題

    • Eager Load + JOIN

    • 截然不同的一種避免N+1次查詢(xún)的方法是,使用二級(jí)緩存。

    N + 1 是關(guān)聯(lián)引入的問(wèn)題, 網(wǎng)上的解釋和例子傾向于拿one-2-many說(shuō)事, 但實(shí)際上one-2-one依然面臨使用多于一條SQL語(yǔ)句加載的問(wèn)題

     

    8. 分離查詢(xún)模型和存儲(chǔ)模型

    適合業(yè)務(wù)關(guān)系的對(duì)象模型未必對(duì)查詢(xún)是高效的. 需要單獨(dú)針對(duì)查詢(xún)建模, 可以用單獨(dú)的索引表來(lái)實(shí)現(xiàn). 在更新業(yè)務(wù)對(duì)象的存儲(chǔ)時(shí)同時(shí)更新索引表

     

    9. 盡量減少查詢(xún)語(yǔ)句

    比如join over multiple select, 比如批量抓取

     

    10. 值類(lèi)型

    不需要有ID, 通常被聚合. 有對(duì)應(yīng)的Class, 但一般沒(méi)有對(duì)應(yīng)的Table, 僅是Table中的幾個(gè)字段

    挑戰(zhàn)在于將對(duì)象語(yǔ)言類(lèi)型系統(tǒng)(和開(kāi)發(fā)者定義的實(shí)體和值類(lèi)型)映射到 SQL/數(shù)據(jù)庫(kù)類(lèi)型系統(tǒng)。 Hibernate: 提供了連接兩個(gè)系統(tǒng)之間的橋梁:對(duì)于實(shí)體類(lèi)型,我們使用class, subclass 等等。對(duì)于值類(lèi)型,我們使用 property, component 及其他,通常跟隨著type屬性。這個(gè)屬性的值是Hibernate 的映射類(lèi)型的名字


    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 在线观看免费黄网站| 亚洲精品免费在线视频| 亚洲av色影在线| 免费在线观看视频网站| 美女免费视频一区二区| 久久久无码精品亚洲日韩蜜桃| 黄页网站免费在线观看| 日韩一级片免费观看| 亚洲系列中文字幕| 看Aⅴ免费毛片手机播放| 亚洲毛片αv无线播放一区| 免费在线观看的网站| 一级毛片免费在线播放| 亚洲欧洲中文日产| 亚洲AV无码专区日韩| 亚洲精品免费在线视频| 亚洲精品视频免费观看| 亚洲综合久久精品无码色欲| 亚洲无人区午夜福利码高清完整版 | 国产亚洲综合一区柠檬导航| 午夜免费福利在线| 99re6在线视频精品免费下载| 亚洲AV无码久久精品成人| 德国女人一级毛片免费| 污视频在线免费观看| 免费大片av手机看片| 亚洲婷婷第一狠人综合精品| 国产成人亚洲精品青草天美| 天堂亚洲免费视频| eeuss影院免费直达入口| 国产精品亚洲专区在线观看| 久久久久久亚洲av成人无码国产| 四虎永久精品免费观看| 日韩av无码成人无码免费| 久久久久成人精品免费播放动漫| 久香草视频在线观看免费| 亚洲精品国产综合久久久久紧| 中文字幕亚洲日本岛国片| 国产色婷婷精品免费视频| 国产在线国偷精品产拍免费| 50岁老女人的毛片免费观看|