成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

JPA2.1 中三個(gè)提升應(yīng)用性能的新功能

qpwoeiru96 / 2610人閱讀

摘要:只用語(yǔ)句,也能完成很多事情,如果不夠,你還可以調(diào)用數(shù)據(jù)庫(kù)的特定功能和存儲(chǔ)過(guò)程。在中,并沒(méi)有針對(duì)存儲(chǔ)過(guò)程的實(shí)際支持,本地查詢是調(diào)用存儲(chǔ)過(guò)程的唯一方式。規(guī)范引入了幾個(gè)新的功能以應(yīng)對(duì)這些低效操作,比如實(shí)體圖,條件更新和存儲(chǔ)過(guò)程查詢。

經(jīng)常在網(wǎng)上看到開(kāi)發(fā)者們抱怨 JPA 性能低下的帖子或文章,但如果仔細(xì)查看這些性能問(wèn)題,常會(huì)發(fā)現(xiàn)導(dǎo)致問(wèn)題的根本原因大致包括以下幾個(gè):

使用過(guò)多的 SQL 查詢從數(shù)據(jù)庫(kù)中獲取所需的實(shí)體信息,即我們常說(shuō)的n+1查詢問(wèn)題

逐個(gè)更新實(shí)體,而不是使用單條語(yǔ)句進(jìn)行更新

使用 Java 應(yīng)用程序而非數(shù)據(jù)庫(kù)進(jìn)行大量數(shù)據(jù)處理

JPA提供了處理這類(lèi)問(wèn)題的方法,并給 JPA2.1 增加了一些額外功能,可以極大地提升性能表現(xiàn),筆者將在本文中解釋如何利用 JPA2.1 的功能避免上述問(wèn)題。

順便提一下,如果想了解Java項(xiàng)目中更多的典型性能問(wèn)題,可以參考筆者最近發(fā)布的基于性能調(diào)查結(jié)果的深度報(bào)告,如果你在尋找 JPA 資源,點(diǎn)擊此鏈接便可獲取JPA2.1特征的備忘清單。接下來(lái)我們來(lái)看看如何用JPA來(lái)解決現(xiàn)有的性能問(wèn)題。

解決「SQL 查詢過(guò)多」的問(wèn)題

根據(jù)以往的經(jīng)驗(yàn),使用過(guò)多的 SQL 查詢獲取所要求的實(shí)體是導(dǎo)致性能問(wèn)題最普遍的原因。

即使是看起來(lái)最簡(jiǎn)單的查詢,如果操作不當(dāng),也會(huì)觸發(fā)幾十次甚至上百次的 SQL 查詢。而且,你在本節(jié)中可以看到,這類(lèi)不當(dāng)操作不一定會(huì)出現(xiàn)在查詢語(yǔ)句中,而可能只是幾個(gè)配置不當(dāng)?shù)淖⒔狻K?,如果你覺(jué)得這個(gè)問(wèn)題不會(huì)造成影響,請(qǐng)三思。

如果在你的項(xiàng)目中出現(xiàn)以下幾段代碼,你會(huì)怎么想?

List authors = this.em.createQuery("SELECT a FROM Author a",
        Author.class).getResultList();

for (Author a : authors) {
    System.out.println("作者 "
            + a.getFirstName()
            + " "
            + a.getLastName()
            + " 書(shū)籍信息 "
            + a.getBooks()
                    .stream()
                    .map(b -> b.getTitle() + "("
                            + b.getReviews().size() + " 評(píng)論)")
                    .collect(Collectors.joining(", ")));
}

上面的代碼段會(huì)打印所有作者的姓名及其書(shū)名,看起來(lái)非常簡(jiǎn)單,但你是否想過(guò)它給數(shù)據(jù)庫(kù)發(fā)送了多少次查詢?一次?還是兩次?或者 Author、Book、Review 實(shí)體各一次?

實(shí)際上,這取決于數(shù)據(jù)庫(kù)中作者的人數(shù)。如果數(shù)據(jù)庫(kù)較小,里面只有11名作者和6本書(shū)。那么這段代碼會(huì)觸發(fā)12次查詢,其中1次用于獲取所有作者姓名,另外11次給每位作者匹配書(shū)名。這一問(wèn)題被稱(chēng)作 n+1 查詢問(wèn)題,無(wú)論我們使用的是 MySQL、SqlServer 還是其他數(shù)據(jù)庫(kù),都容易出現(xiàn)此類(lèi)問(wèn)題。因此在生產(chǎn)環(huán)境中,隨著數(shù)據(jù)量不斷增大,代碼的性能就越差。

我們可以通過(guò)多種方法,用一次查詢獲取所有要求的實(shí)體信息 ,從而避免這一情況。在筆者看來(lái),使用 @NamedEntityGraph 來(lái)解決此問(wèn)題是最新,也最好的方法。

實(shí)體圖通過(guò)獨(dú)立于查詢的方法指定應(yīng)該從數(shù)據(jù)庫(kù)中獲取的實(shí)體的圖。這意味著,你需要為實(shí)體圖創(chuàng)建一個(gè)獨(dú)立的定義,并在需要時(shí)與查詢合并。下段代碼展示了如何定義根據(jù)作者名提取書(shū)名的 @NamedEntityGraph。

@Entity
@NamedEntityGraph(name = "graph.AuthorBooks", attributeNodes = @NamedAttributeNode("books"))
public class Author implements Serializable {
…
}

現(xiàn)在,實(shí)體管理器可以用這個(gè)圖為參考,通過(guò)一次查詢獲取所有作者和書(shū)名。在圖的定義中可以看到,筆者只提供了包含相關(guān)實(shí)體的屬性名稱(chēng)。因此,筆者將@NamedEntityGraph作為loadgraph (負(fù)載圖),這樣便可提取其他所有屬性及其定義的獲取類(lèi)型,如下所示:

EntityGraph graph = this.em.getEntityGraph("graph.AuthorBooks");

List authors = this.em
.createQuery("SELECT DISTINCT a FROM Author a", Author.class)
.setHint("javax.persistence.loadgraph", graph).getResultList();

該示例展示了一個(gè)非常簡(jiǎn)單的實(shí)體圖,在實(shí)際的應(yīng)用中,很可能會(huì)用到更復(fù)雜的圖,但這也不成問(wèn)題。你可以定義多個(gè) @NamedAttributeNodes 以定義更復(fù)雜的圖,也可以用 @NamedSubGraph 注解來(lái)創(chuàng)建多層次的圖。如果想了解更多關(guān)于 @NamedEntityGraphs 的信息,請(qǐng)點(diǎn)擊實(shí)體圖使用方式詳解。

在某些使用案例中,你可能還需要用更動(dòng)態(tài)的方式來(lái)定義實(shí)體圖,比如,根據(jù)一些輸入?yún)?shù)進(jìn)行定義。在此類(lèi)案例中,通過(guò) Java API 用編程的方式定義實(shí)體圖效果更佳。

解決「逐個(gè)更新實(shí)體」的問(wèn)題

逐個(gè)更新實(shí)體是造成 JPA 性能問(wèn)題的另一個(gè)常見(jiàn)原因。作為 Java 開(kāi)發(fā)者,我們習(xí)慣處理對(duì)象,并用面向?qū)ο蟮姆绞剿伎紗?wèn)題。盡管這是實(shí)現(xiàn)復(fù)雜邏輯和應(yīng)用的好方法,但也是處理數(shù)據(jù)庫(kù)時(shí)導(dǎo)致性能退化的一個(gè)常見(jiàn)原因。

從面向?qū)ο蟮慕嵌葋?lái)看,對(duì)實(shí)體進(jìn)行更新和刪除操作是完全可以接受的。但當(dāng)你不得不更新一大組實(shí)體時(shí),這種操作就會(huì)非常低效。持久性提供者(Persistence Provider)將為每個(gè)更新實(shí)體創(chuàng)建一個(gè)更新語(yǔ)句,并在下一次 flush 操作時(shí)發(fā)送至數(shù)據(jù)庫(kù)中。

然而,SQL 提供了一個(gè)更為高效的方式。它允許你創(chuàng)建可一次性更新多個(gè)實(shí)體的更新語(yǔ)句。你還可以對(duì) JPA 2.1 引入的 CriteriaUpdateCriteriaDelete 語(yǔ)句進(jìn)行同樣的操作。

如果你之前用過(guò) criteria 條件查詢,肯定對(duì)新的 CriteriaUpdate 以及 CriteriaDelete 語(yǔ)句非常熟悉,更新和刪除操作的創(chuàng)建方式幾乎與 JPA 2.0 中引入的 criteria 條件查詢創(chuàng)建方式一樣。

在下面的代碼段中可以看到,你需要從實(shí)體管理器中獲取 CriteriaBuilder 并用它創(chuàng)建 CriteriaUpdate 對(duì)象,對(duì) CriteriaQuery 進(jìn)行的操作與此類(lèi)似,主要區(qū)別在于用于定義更新操作的 set 方法。

CriteriaBuilder cb = this.em.getCriteriaBuilder();
// create update
CriteriaUpdate update = cb.createCriteriaUpdate(Author.class);
// set the root class
Root a = update.from(Author.class);
// set update and where clause
update.set(Author_.firstName, cb.concat(a.get(Author_.firstName), " - updated"));
update.where(cb.greaterThanOrEqualTo(a.get(Author_.id), 3L));

// perform update
Query q = this.em.createQuery(update);
q.executeUpdate();

CriteriaDelete 操作中,你只需要在實(shí)體管理器中調(diào)用 createCriteriaDelete 方法以獲取 CriteriaDelete 對(duì)象,并用它來(lái)定義與上例類(lèi)似的 FROMWHERE 查詢部分。

在數(shù)據(jù)庫(kù)中處理數(shù)據(jù)

作為 Java 開(kāi)發(fā)者,我們傾向于在 Java 中實(shí)現(xiàn)所有的應(yīng)用邏輯,這也是造成性能問(wèn)題的一大常見(jiàn)原因。別誤會(huì),在 Java 中實(shí)現(xiàn)邏輯的好處很多,但如果將部分邏輯實(shí)現(xiàn)在數(shù)據(jù)庫(kù)中,只把結(jié)果發(fā)送到業(yè)務(wù)邏輯層,也能得到很好的效果。

在數(shù)據(jù)庫(kù)中執(zhí)行邏輯的方法很多。只用 SQL 語(yǔ)句,也能完成很多事情,如果不夠,你還可以調(diào)用數(shù)據(jù)庫(kù)的特定功能和存儲(chǔ)過(guò)程。在本文中,筆者將仔細(xì)探討存儲(chǔ)過(guò)程,更確切地說(shuō)是探討調(diào)用存儲(chǔ)過(guò)程的方式。

在 JPA 2.0 中,并沒(méi)有針對(duì)存儲(chǔ)過(guò)程的實(shí)際支持,本地查詢是調(diào)用存儲(chǔ)過(guò)程的唯一方式。JPA 2.1.引入了 @NamedStoredProcedureQuery 和更為動(dòng)態(tài)的 StoredProcedureQuery,改變了這一現(xiàn)狀。在本文中,筆者將重點(diǎn)關(guān)注基于注解的、用 @NamedStoredProcedureQuery 進(jìn)行調(diào)用的存儲(chǔ)過(guò)程的定義。筆者在自己的博客中詳細(xì)介紹了動(dòng)態(tài)存儲(chǔ)過(guò)程查詢 。

在下面代碼段中可以看到, @NamedStoredProcedureQuery 的定義非常簡(jiǎn)潔,你需要指定查詢的名稱(chēng)、數(shù)據(jù)庫(kù)中的存儲(chǔ)過(guò)程名稱(chēng)以及輸入和輸出參數(shù)。在本例中,筆者用輸入?yún)?shù) xy 調(diào)用存儲(chǔ)過(guò)程 calculate,期望的輸出參數(shù)為 sum,其它支持的參數(shù)類(lèi)型還有用于輸入和輸出的參數(shù) INPUT 和用于檢索結(jié)果集的 REF_COURSOR

@NamedStoredProcedureQuery(
name = "calculate",
procedureName = "calculate",
parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, type = Double.class, name = "x"),
@StoredProcedureParameter(mode = ParameterMode.IN, type = Double.class, name = "y"),
@StoredProcedureParameter(mode = ParameterMode.OUT, type = Double.class, name = "sum") })

@NamedStoredProcedureQuery 的使用方法與 @NamedQuery 相似,你需要向?qū)嶓w管理器的createNamedStoredProcedureQuery 方法提供查詢名稱(chēng),以便在本次查詢中獲取 StoredProcedureQuery 對(duì)象,然后,用 setParameter 方法設(shè)定輸入?yún)?shù),之后再用 execute 方法調(diào)用存儲(chǔ)過(guò)程。

StoredProcedureQuery query = this.em.createNamedStoredProcedureQuery("calculate");
query.setParameter("x", 1.23d);
query.setParameter("y", 4.56d);
query.execute();
Double sum = (Double) query.getOutputParameterValue("sum");
總結(jié)

JPA 給數(shù)據(jù)庫(kù)存儲(chǔ)和檢索帶來(lái)諸多便利。通過(guò)這一工具,可快速開(kāi)展項(xiàng)目,解決大部分問(wèn)題,但也更容易導(dǎo)致實(shí)現(xiàn)非常低效的持久層。由此,普遍存在的問(wèn)題包括:使用過(guò)多查詢獲取所需數(shù)據(jù)、逐個(gè)更新實(shí)體以及在 Java 中執(zhí)行所有邏輯。

JPA 2.1規(guī)范引入了幾個(gè)新的功能以應(yīng)對(duì)這些低效操作,比如實(shí)體圖(entity graphs),條件更新(criteria update)和存儲(chǔ)過(guò)程查詢(stored procedure queries)。筆者的JPA2.1新功能備忘單囊括了JPA 2.1的這些功能及其他新功能,你可以免費(fèi)下載。

(編譯自:http://zeroturnaround.com/rebellabs/three-jpa-2-1-features-that-will-boost-your-applications-performance/)

OneAPM 為您提供端到端的 Java 應(yīng)用性能解決方案,我們支持所有常見(jiàn)的 Java 框架及應(yīng)用服務(wù)器,助您快速發(fā)現(xiàn)系統(tǒng)瓶頸,定位異常根本原因。分鐘級(jí)部署,即刻體驗(yàn),Java 監(jiān)控從來(lái)沒(méi)有如此簡(jiǎn)單。想閱讀更多技術(shù)文章,請(qǐng)?jiān)L問(wèn) OneAPM 官方技術(shù)博客。

本文轉(zhuǎn)自 OneAPM 官方博客

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/17486.html

相關(guān)文章

  • JPA2.1 三個(gè)提升應(yīng)用性能功能

    摘要:只用語(yǔ)句,也能完成很多事情,如果不夠,你還可以調(diào)用數(shù)據(jù)庫(kù)的特定功能和存儲(chǔ)過(guò)程。在中,并沒(méi)有針對(duì)存儲(chǔ)過(guò)程的實(shí)際支持,本地查詢是調(diào)用存儲(chǔ)過(guò)程的唯一方式。規(guī)范引入了幾個(gè)新的功能以應(yīng)對(duì)這些低效操作,比如實(shí)體圖,條件更新和存儲(chǔ)過(guò)程查詢。 經(jīng)常在網(wǎng)上看到開(kāi)發(fā)者們抱怨 JPA 性能低下的帖子或文章,但如果仔細(xì)查看這些性能問(wèn)題,常會(huì)發(fā)現(xiàn)導(dǎo)致問(wèn)題的根本原因大致包括以下幾個(gè): 使用過(guò)多的 SQL 查詢從...

    ormsf 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<