日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

本文介紹了最佳做法是在添加到@ManyToMany的所有者端集合時(shí)避免選擇所有行的處理方法,對(duì)大家解決問(wèn)題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧!

問(wèn)題描述

當(dāng)添加到表示@ManyToMany關(guān)聯(lián)的所屬方的集合時(shí),我的JPA實(shí)現(xiàn)(Hibernate)將首先選擇關(guān)聯(lián)中的所有行,以確定該實(shí)體是否已經(jīng)存在于集合中。

我了解這背后的機(jī)制,但在處理大型連接表時(shí),這不是很好的性能。當(dāng)我知道需要插入條目時(shí),避免加載連接表的所有元素的最佳做法是什么?

我將以一個(gè)典型的用戶/角色場(chǎng)景為例,為簡(jiǎn)潔起見(jiàn),省略了getters/setters/初始化式:

@Entity
public class User {
    @Id
    private Long id;

    @ManyToMany
    private Set<Role> roles;
}

@Entity
public class Role {
    @Id
    private Long id;

    private String name;

    @ManyToMany(mappedBy = "roles")
    private Set<User> users;
}

我讓User成為擁有方,這樣JPA將跟蹤對(duì)User.Roles的更改。

以下代碼導(dǎo)致該問(wèn)題:

User user = em.find(User.class, 1L);
Role role = em.find(Role.class, 1L);

// This line causes the issue
user.getRoles().add(role);

em.persist(user);

當(dāng)我添加到用戶角色時(shí),執(zhí)行以下SELECT操作:

select
     roles0_.users_id as users_id1_20_0_,
     roles0_.roles_id as roles_id2_21_0_,
     role1_.id as id1_17_1_,
     role1_.name as name2_17_1_ 
from User_Role roles0_ 
inner join Role role1_ on roles0_.roles_id=role1_.id 
where roles0_.users_id=?

這對(duì)于較小的集合來(lái)說(shuō)很好,但對(duì)于較大的集合就有問(wèn)題。

我可以想到以下解決方案,我想知道我應(yīng)該選擇哪一個(gè),或者是否有更好的方法來(lái)做到這一點(diǎn)?

1.執(zhí)行本機(jī)查詢:

INSERT INTO User_Role (users_id, roles_id) VALUES (1, 1)

2.為連接表創(chuàng)建實(shí)體:

@Entity
IdClass(UserRole.PK)
public class UserRole {
    @Id
    private User user;
    @Id
    private Role role;

    public static class PK {
        private User user;
        private Role role;
    }
}

然后我可以運(yùn)行:

User user = em.find(User.class, 1L);
Role role = em.find(Role.class, 1L);
UserRole userRole = new UserRole(user, role);
em.persist(userRole);

我傾向于對(duì)INSERT使用原生查詢,但我希望得到一些反饋,了解執(zhí)行此操作的最‘JPA’方式是什么。

推薦答案

《使用Hibernate的Java持久性》一書(shū)(第298頁(yè))指出,多對(duì)多通常最好使用關(guān)聯(lián)類(lèi)(有點(diǎn)像您在第二個(gè)解決方案中已有的UserRole),然后為兩端映射兩個(gè)一對(duì)多關(guān)系–即每個(gè)用戶有多個(gè)UserRole,每個(gè)角色有多個(gè)UserRole。這是最”JPA”的做事方式,我想你會(huì)得到你想要的表現(xiàn)。

現(xiàn)在細(xì)微之處:

    關(guān)聯(lián)類(lèi)應(yīng)該有一個(gè)基于用戶和角色的ID的組合鍵,而不是它自己的主鍵。本書(shū)給出了一個(gè)在Association類(lèi)中創(chuàng)建一個(gè)@Embedble靜態(tài)內(nèi)部類(lèi)的示例,該類(lèi)包含兩個(gè)主要類(lèi)(在您的例子中是User和Role)的ID。這些ID到關(guān)聯(lián)表中的列的映射是在這個(gè)內(nèi)部類(lèi)中完成的。
    在您向其傳遞特定角色和用戶的關(guān)聯(lián)類(lèi)的構(gòu)造函數(shù)中,您將填充內(nèi)部類(lèi),然后將”this”(即您正在創(chuàng)建的關(guān)聯(lián)實(shí)例)添加到傳入的用戶和角色的集合中(例如,role.getUserRoles().add(This))。
    刪除關(guān)聯(lián)時(shí),必須同時(shí)從用戶和角色中刪除該關(guān)聯(lián)。也就是說(shuō),在角色端,您將執(zhí)行以下操作:role.getUserRoles().Remove(UserRole),然后您將在用戶端執(zhí)行相同的操作,然后刪除關(guān)聯(lián):ession.ete(UserRole)。

如果您遵循這些步驟,Hibernate將知道正在發(fā)生的一切,并且您的緩存應(yīng)該是好的。您還可以使用級(jí)聯(lián)啟用傳遞性持久性。

編輯:如上所述,這實(shí)際上并不會(huì)消除試圖避免的查詢。經(jīng)過(guò)進(jìn)一步思考,我沒(méi)有一個(gè)可以消除查詢的答案,但我可以指出為什么JPA的行為方式如您所見(jiàn)。在原始設(shè)置中,每一項(xiàng)都有其他內(nèi)容的。由于集合是唯一的,并且JPA提供程序遵循集合語(yǔ)義,因此它們必須確保關(guān)系是唯一的。因此,如果您添加一個(gè)關(guān)系,它必須進(jìn)行查詢以確保該關(guān)系不存在。它可以只查詢您試圖添加的關(guān)系,也可以查詢整個(gè)集合,然后檢查內(nèi)部。如果您要將多個(gè)內(nèi)容添加到集合中,則后者是更好的方法,而這正是他們針對(duì)此進(jìn)行優(yōu)化的原因。JPA提供程序永遠(yuǎn)不會(huì)做的一件事是,如果您試圖添加重復(fù)的關(guān)系,JPA提供程序永遠(yuǎn)不會(huì)依賴于底層數(shù)據(jù)庫(kù)約束–JPA提供程序更喜歡在Java層處理Java約束

Hibernate還支持袋子選項(xiàng),該選項(xiàng)允許重復(fù),因此可以避免檢查…但這樣,您的數(shù)據(jù)庫(kù)中就會(huì)有重復(fù)的關(guān)系。

這篇關(guān)于最佳做法是在添加到@ManyToMany的所有者端集合時(shí)避免選擇所有行的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,

分享到:
標(biāo)簽:ManyToMany 做法 所有者 是在 添加 選擇 集合
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定