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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jpa获取session_JPA 2 | 获取联接以及我们是否应该使用它们

發(fā)布時間:2023/12/3 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jpa获取session_JPA 2 | 获取联接以及我们是否应该使用它们 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

jpa獲取session

介紹

最近,我一直在與JPA 2中的FETCH JOINS一起使用,以期從數(shù)據(jù)庫中急切地獲取數(shù)據(jù),并且我學(xué)到了很多關(guān)于為什么在日常操作中應(yīng)避免使用Fetch Joins的知識。

今天的博客文章談?wù)摿宋以贔etch上的經(jīng)歷和學(xué)習(xí)(主要基于當(dāng)我在查詢中有很多FETCH JOINS時獲得的評論)。

問題陳述

在我們的項目中,有一種情況是從定義了許多集合值關(guān)聯(lián)的數(shù)據(jù)庫(OneToMany,ManyToMany,也稱為ToMany關(guān)聯(lián))中獲取實體。 這是實體外觀的概念圖(為清楚起見,省略了getter和setter)。 這是實體的極其簡化的示例。 在實際情況下,我們大約有11個關(guān)聯(lián)。

public class ItemRecord {@Idprivate String itemId;@Column(name="author")private String author;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private List costs;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private List notes;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private List stats;}

關(guān)于上述實體,有幾件事需要注意:

  • 它具有3個收藏珍貴的協(xié)會。
  • 所有這些關(guān)聯(lián)都被延遲獲取,因為JPA中“集合有價值的關(guān)聯(lián)”的默認(rèn)獲取策略是“惰性”。

在我們的業(yè)務(wù)實現(xiàn)中,我們有一個轉(zhuǎn)換器,該轉(zhuǎn)換器將DAO層返回的值轉(zhuǎn)換為Business DTO。

因此,我們的業(yè)務(wù)方法的算法如下:

@TransactionAttribute public List searchItemRecords (SearchCriteria sc) {List ir = itemRecordDao.search(sc);List convertedData = recordConverter.convert(ir);return convertedData; }

請注意,整個方法都在Transaction內(nèi)部運行。

每當(dāng)我們從數(shù)據(jù)庫中獲取數(shù)據(jù)時,都不會急切地獲取與成本,統(tǒng)計信息等相關(guān)的數(shù)據(jù)。 但是我們的ItemInformation DTO期望所有數(shù)據(jù)。 因此,當(dāng)首次調(diào)用getCosts或getStatistics時,持久性提供程序(在本例中為Hibernate)向數(shù)據(jù)庫激發(fā)查詢以獲取指定的數(shù)據(jù)。 這為我們創(chuàng)建了N + 1個選擇查詢問題。 如果您不熟悉N + 1選擇或需要刷新,可以在DZone上查看此文章 。

我們大多數(shù)人,包括我在內(nèi),都會選擇N + 1選擇問題的最快,最簡單的解決方案,即使用Fetch Join。 在Internet上發(fā)布的不同博客/文章中也有很多建議。

因此,我也采用了相同的方法。 就我而言,這至少是一種糟糕的方法。

首先讓我們看看如何使用FETCH JOIN。

使用Fetch Join之前的查詢?nèi)缦?#xff1a;

SELECT item FROM ItemRecord item WHERE author=:author;

請注意,查詢采用JPA形式。

該查詢未獲取集合值。 結(jié)果,在翻譯器中,當(dāng)我們對每個ItemRecord執(zhí)行g(shù)etCosts時,將觸發(fā)類似于以下的查詢:

SELECT cost FROM Cost where itemId = :itemId

因此,如果我們有3個ItemRecords,則激發(fā)到數(shù)據(jù)庫的SELECT查詢總數(shù)為:

  • 1用于獲取所有ItemRecords
  • 3個用于獲取每個ItemRecord的成本
  • 3用于獲取每個ItemRecord的注釋
  • 3個用于獲取每個ItemRecord的統(tǒng)計信息

即(3乘3)+ 1

當(dāng)將其轉(zhuǎn)換為N乘以M +1時,

哪里,

  • N是找到的主要實體記錄的數(shù)量
  • M是主要實體中Collection值關(guān)聯(lián)的數(shù)量
  • 1個查詢,用于獲取所有主要實體

在實際情況下,我們有11個關(guān)聯(lián)。 因此,對于每個主要ItemRecord實體,我們將觸發(fā)11個SELECT查詢。 激發(fā)的查詢數(shù)量乘以找到的每個ItemRecord。

使得集合值關(guān)聯(lián)成為EAGER是不可行的,因為在實體上運行的許多其他查詢僅需要選定的數(shù)據(jù)。

這不是最佳解決方案。 必須做一些事情,很多互聯(lián)網(wǎng)文章建議使用FETCH JOINS,因為它們最容易實現(xiàn)并解決了(N Time M +1)個查詢問題。

因此,我決定在查詢中使用FETCH Joins來針對給定場景急切地獲取所有數(shù)據(jù)。

該查詢類似于:

SELECT item FROM ItemRecordJOIN FETCH item.costs, JOIN FETCH item.notes, JOIN FETCHitem.stats;

跨欄1

我很快意識到該查詢在我的情況下將無法使用,因為我可以擁有一個與之不相關(guān)的統(tǒng)計信息,而在這種情況下,上述查詢不會向我返回那個ItemRecord(因為ORM的工作方式)因此我將獲得不完整的數(shù)據(jù)。

因此,接下來我轉(zhuǎn)到了LEFT JOIN FETCH,即使某些關(guān)聯(lián)關(guān)系為空,它也將給我ItemRecord實體返回。 查詢?nèi)缦滤?#xff1a;

SELECT item FROM ItemRecordLEFT JOIN FETCH item.costs, LEFT JOIN FETCH item.notes, LEFT JOIN FETCH item.stats;

跨欄2

當(dāng)我運行單元測試以測試上述查詢時,出現(xiàn)了異常:

javax.persistence.PersistenceException: org.hibernate.HibernateException: cannot simultaneously fetch multiple bags

問題是什么?

問題是我在實體中使用列表作為集合類型。 使用列表會混淆JPA /Hibernate。 這篇文章很好地記錄了這種困惑。

為了解決此問題,我選擇使用Set而不是List,主要是因為它是上述博客文章提供的三種解決方案中最簡單的方法,并且也很有意義(至少在我實現(xiàn)時)。

因此,我將Entity更改為Set而不是List,并且修改后的實體如下所示:

public class ItemRecord {@Idprivate String itemId;@Column(name="author")private String author;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private Set costs;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private Set notes;@OneToMany(cascade = CascadeType.ALL, mappedBy = "item")private Set stats;}

我再次運行測試用例,并且測試查詢的測試用例成功。 耶皮 但是,我的另一個測試用例正在測試注釋部分中的條目失敗。 看一下測試用例,我意識到我需要按照特定的順序輸入數(shù)據(jù),并且我使用的是HashSet,但沒有順序。 解決方案很簡單。 使用LinkedHashSet維護(hù)元素的順序。

使用LinkedHashSet可以解決問題,并且我的測試用例通過了。

我很高興,但我的幸福短暫。

跨欄3

我還有另一個測試用例,對于給定的ItemRecord來說,它需要3個成本對象。 我轉(zhuǎn)到設(shè)置實現(xiàn)后,測試立即開始失敗。 事實證明,我的哈希碼不正確,并且我的“成本實體”的實現(xiàn)等于“實現(xiàn)”,“成本實體”為兩個不同的實體返回相同的哈希碼,結(jié)果,由于Set不允許重復(fù)值,因此僅持久保留了一個實體。

因此,我接下來要做的就是為我的所有實體使用適當(dāng)?shù)腍ashCode和Equals實現(xiàn)。

最終關(guān)卡

最終,當(dāng)我所有的測試用例開始通過時,我進(jìn)行了代碼審查,并將其發(fā)送給團(tuán)隊。

第一個嚇到我的是我的技術(shù)主管。 :)

他只是生氣地看著FETCH JOINS。 原因? 原因是LEFT FETCH JOINs返回所有數(shù)據(jù)的笛卡爾積。 隨著我們生產(chǎn)中的數(shù)據(jù)量的增加,甚至無法支持ItemRecord上的多個選擇將成為一場噩夢。 整個問題可以在此博客文章中輕松理解。


因此,我試圖解決性能問題,事實證明我實際上是在制造更大的性能問題。 :)

刪除了轉(zhuǎn)移到FETCH JOIN的整個解決方案,因此決定進(jìn)一步研究為什么我們需要UI上的全部數(shù)據(jù),以及為什么不能將獲取數(shù)據(jù)分成較小的專用事務(wù)。

摘要:

使用Fetch Joins的整個過程使我很好地了解了Joins的總體工作原理以及使用它們時的期望。

希望您喜歡這篇博客文章。 如果您想繼續(xù)閱讀有趣的帖子,可以關(guān)注我的博客。

參考: JPA 2 | 從JavaWorld Blog博客中獲取Fetch Joins,以及是否應(yīng)該從我們的JCG合作伙伴 Anuj Kumar 使用它們 。

翻譯自: https://www.javacodegeeks.com/2013/07/jpa-2-fetch-joins-and-whether-we-should-use-them.html

jpa獲取session

總結(jié)

以上是生活随笔為你收集整理的jpa获取session_JPA 2 | 获取联接以及我们是否应该使用它们的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。