藏品一覽

好了,您已經了解瞭如何映射簡單類型。現在是時候轉向更有趣的問題了——如何映射對象集合。

我們可以將對象分為 5 組:

  • Array - 對像數組
  • 列表- 對象列表
  • Set - 一組對象
  • 地圖- 對象字典
  • 集合——對象的集合

以及一個帶有集合字段的類的示例:

@Entity
@Table(name="user")
class User {
   @Id
   @Column(name="id")
   public Integer id;

   @magical-annotation
   public List messages;
}

那麼這個能讓我們存儲的不是一個字段而是多個值的神奇註解是什麼?

此註釋稱為@ElementCollection。例子:

@Entity
@Table(name="user")
class User  {
   @Id
   @Column(name="id")
   public Integer id;

   @ElementCollection
   public List<String> messages;
}

它寫得非常簡單,但它的工作並不平凡。

輔助表

Entity 類的所有包含許多元素並用@ElementCollection註解標記的字段都包含在數據庫中的一個特殊的輔助表中。事實上,這是合乎邏輯的。

該表可以包含兩種形式的數據:

  • Ordered (List, Map) 包含三列:
    • 鍵列(外鍵)——對父對象 ID 的引用。
    • 索引列- 集合中的位置/索引。
    • 元素列- 值。
  • 無序(Set)包含兩列:
    • 鍵列(外鍵)——對父對象 ID 的引用。
    • 元素列- 值。

您還可以使用註釋顯式設置此表的名稱:

@CollectionTable(name="table_name")

例子:

@Entity
@Table(name="user")
class User {
   @Id
   @Column(name="id")
   public Integer id;

   @ElementCollection
   @CollectionTable(name="user_message")
   public List<String> messages;
}

重要的!如果沒有指定@CollectionTable註解,那麼Hibernate會根據類名和字段名自己構建表名:User和字段訊息將表命名為“User_messages”。

收藏 收藏

但是我們不要把輔助表的創建交給Hibernate,我們自己創建。首先我們需要創建一個包含兩列的表:

CREATE TABLE user_message {
    user_id INT,
    message VARCHAR(255)
};

請注意,此表沒有自己的 ID 列。這是輔助表的主要特點。稍後您將熟悉其他類型的輔助表。

現在我們需要將這張表映射到我們的字段訊息用戶類中。這看起來像這樣:

@Entity
@Table(name="user")
class User {
   @Id
   @Column(name="id")
   public Integer id;

   @ElementCollection
   @CollectionTable(name="user_message", joinColumns = @JoinColumn(name = "user_id"))
   @Column(name = "message")
   public Set<String> messages;
}

這裡有兩件事值得關注。

首先,用@Column (name = "message")註釋指定的消息列位於user_message 輔助表中,而不是用戶表中。

其次,在@JoinColumn(name = "user_id")註解中,我們指定了user_id列的名稱,它指的是user表的id。這是為了讓 Hibernate 知道如何正確地組合它們。

收藏

如果要將列表或數組的有序元素存儲在輔助表中,則需要一個包含三列的表:

CREATE TABLE user_message {
    user_id INT,
    index INT,
    message VARCHAR(255)
};

如果你不喜歡“index”這個列名,或者你不能改變它,你可以在映射時指定一個不同的名字。為此,您需要使用@Index註釋。

例子:

@Entity
@Table(name="user")
class User {
   @Id
   @Column(name="id")
   public Integer id;

   @ElementCollection
   @CollectionTable(name="user_message",
       	indexes = { @Index(columnList = "list_index") }
       	joinColumns = @JoinColumn(name = "user_id"))
   @Column(name = "message")
   public List<String> messages;
}

地圖集

最後,你不僅要存儲一個集合,還要存儲一個 HashMap,你需要在一個輔助表中為它存儲兩列:

CREATE TABLE user_message {
    user_id INT,
    key VARCHAR(255),
    message VARCHAR(255)
};

為了指定地圖的鍵,您需要@MapKeyColumn註釋。

例子:

@Entity
@Table(name="user")
class User {
   @Id
   @Column(name="id")
   public Integer id;

   @ElementCollection
   @CollectionTable(name="user_message", joinColumns = @JoinColumn(name = "user_id"))
   @MapKeyColumn(name = "key")
   @Column(name = "message")
   public Map<String, String> messages;
}

您可以在官方文檔中找到更多信息。