JPA - 雙向多對多對映
阿新 • • 發佈:2018-11-12
在雙向多對多關係中,我們必須指定一個關係維護端(owner side),可以通過 @ManyToMany 註釋中指定 mappedBy 屬性來標識其為關係維護端。
【1】item與Category
item:category = N:N ,item為關係維護端(主),category為從。
item類如下:
@Table(name="JPA_ITEMS") @Entity public class Item { private Integer id; private String itemName; private Set<Category> categories = new HashSet<>(); @GeneratedValue @Id public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(name="ITEM_NAME") public String getItemName() { return itemName; } public void setItemName(String itemName) { this.itemName = itemName; } //使用 @ManyToMany 註解來對映多對多關聯關係 //使用 @JoinTable 來對映中間表 //1. name 指向中間表的名字 //2. joinColumns 對映當前類所在的表在中間表中的外來鍵 //2.1 name 指定外來鍵列的列名 //2.2 referencedColumnName 指定外來鍵列關聯當前表的哪一列 //3. inverseJoinColumns 對映關聯的類所在中間表的外來鍵 @JoinTable(name="ITEM_CATEGORY", joinColumns={@JoinColumn(name="ITEM_ID", referencedColumnName="ID")}, inverseJoinColumns={@JoinColumn(name="CATEGORY_ID", referencedColumnName="ID")}) @ManyToMany public Set<Category> getCategories() { return categories; } public void setCategories(Set<Category> categories) { this.categories = categories; } }
category類如下:
@Table(name="JPA_CATEGORIES") @Entity public class Category { private Integer id; private String categoryName; private Set<Item> items = new HashSet<>(); @GeneratedValue @Id public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(name="CATEGORY_NAME") public String getCategoryName() { return categoryName; } public void setCategoryName(String categoryName) { this.categoryName = categoryName; } @ManyToMany(mappedBy="categories") public Set<Item> getItems() { return items; } public void setItems(Set<Item> items) { this.items = items; } }
【2】多對多持久化操作
示例程式碼如下:
//多對多的儲存 @Test public void testManyToManyPersist(){ Item i1 = new Item(); i1.setItemName("i-1"); Item i2 = new Item(); i2.setItemName("i-2"); Category c1 = new Category(); c1.setCategoryName("C-1"); Category c2 = new Category(); c2.setCategoryName("C-2"); //設定關聯關係 i1.getCategories().add(c1); i1.getCategories().add(c2); i2.getCategories().add(c1); i2.getCategories().add(c2); c1.getItems().add(i1); c1.getItems().add(i2); c2.getItems().add(i1); c2.getItems().add(i2); //執行儲存 entityManager.persist(i1); entityManager.persist(i2); entityManager.persist(c1); entityManager.persist(c2); }
控制檯輸出如下:
Hibernate:
insert
into
JPA_ITEMS
(ITEM_NAME)
values
(?)
Hibernate:
insert
into
JPA_ITEMS
(ITEM_NAME)
values
(?)
Hibernate:
insert
into
JPA_CATEGORIES
(CATEGORY_NAME)
values
(?)
Hibernate:
insert
into
JPA_CATEGORIES
(CATEGORY_NAME)
values
(?)
Hibernate:
insert
into
ITEM_CATEGORY
(ITEM_ID, CATEGORY_ID)
values
(?, ?)
Hibernate:
insert
into
ITEM_CATEGORY
(ITEM_ID, CATEGORY_ID)
values
(?, ?)
Hibernate:
insert
into
ITEM_CATEGORY
(ITEM_ID, CATEGORY_ID)
values
(?, ?)
Hibernate:
insert
into
ITEM_CATEGORY
(ITEM_ID, CATEGORY_ID)
values
(?, ?)
資料庫結果如下:
【3】雙向多對多獲取操作
先獲取非維護關聯關係的一方,程式碼示例如下:
@Test
public void testManyToManyFind(){
Category category = entityManager.find(Category.class, 3);
System.out.println(category.getCategoryName());
System.out.println(category.getItems().size());
}
控制檯輸出如下:
如果先獲取維護關聯關係的一方呢?
示例程式碼如下:
@Test
public void testManyToManyFind(){
Item item = entityManager.find(Item.class, 5);
System.out.println(item.getItemName());
System.out.println(item.getCategories().size());
}
控制檯輸出如下:
故而總結如下:
對於關聯的集合物件, 預設使用懶載入的策略;
使用維護關聯關係的一方獲取, 還是使用不維護關聯關係的一方獲取, SQL 語句相同。