首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Hibernate 多對多自關聯(好友關係)建議改用單向一對多 + 中間表複合主鍵,避免雙向多對多配置複雜且效能差

     編輯:程式設計疑難解答

使用者嘗試用 Hibernate 多對多自關聯(User ↔ User)實現好友關係,遇到關係表不寫入資料的問題。Hibernate 雙向多對多自關聯配置極易出錯(`mappedBy`、`joinColumns`/`inverseJoinColumns` 易混淆),且查詢會產生龐大 SQL。

推薦模型:單向一對多 + 關聯實體


// User 實體
@Entity
public class User {
    @Id Long id;
    String username;
    // 單向:一個用戶擁有多個好友關係記錄
    @OneToMany(mappedBy = "user")
    List friendships;
}

// 關聯實體(中間表)
@Entity
@IdClass(FriendshipPK.class) // 複合主鍵
public class Friendship {
    @Id @ManyToOne User user;        // 擁有者
    @Id @ManyToOne User friend;      // 好友
    String remark;                   // 擴展欄位:備註、分組、建立時間等
}

// 複合主鍵類
public class FriendshipPK implements Serializable {
    Long user;   // 對應 User.id
    Long friend; // 對應 User.id
}

操作範例


// 加好友
Friendship f = new Friendship();
f.setUser(currentUser);
f.setFriend(targetUser);
f.setRemark("同事");
session.save(f);

// 查我的好友
List friends = session.createQuery(
    "SELECT f.friend FROM Friendship f WHERE f.user = :me", User.class)
    .setParameter("me", currentUser)
    .list();

優勢

  • 配置簡單:無 `mappedBy` 雙向維護,單向關聯清晰。
  • 擴展性強:`Friendship` 可隨意加欄位(狀態、標籤、來源、時間)。
  • 查詢高效:直接查中間表,避免 Hibernate 多對多產生的笛卡兒積/多次 JOIN。
  • 支援單向/雙向好友:若需雙向,插入兩條記錄(A→B、B→A)即可,邏輯可控。

MyBatis 對比

若專案已用 MyBatis,手寫 SQL 更直觀:



結論:**自關聯多對多請拆解為關聯實體 + 一對多**,無論 Hibernate 或 MyBatis 都更穩健、可維護。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved