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

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

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

本文介紹了最佳做法是在添加到@ManyToMany的所有者端集合時避免選擇所有行的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

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

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

我將以一個典型的用戶/角色場景為例,為簡潔起見,省略了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將跟蹤對User.Roles的更改。

以下代碼導致該問題:

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);

當我添加到用戶角色時,執(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=?

這對于較小的集合來說很好,但對于較大的集合就有問題。

我可以想到以下解決方案,我想知道我應該選擇哪一個,或者是否有更好的方法來做到這一點?

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

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

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

@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;
    }
}

然后我可以運行:

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

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

推薦答案

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

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

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

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

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

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

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

分享到:
標簽:ManyToMany 做法 所有者 是在 添加 選擇 集合
用戶無頭像

網(wǎng)友整理

注冊時間:

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

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

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

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

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

答題星2018-06-03

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

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

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

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

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

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定