首頁 > 軟體

使用JPA雙向多對多關聯關係@ManyToMany

2022-06-13 14:04:26

JPA雙向多對多關聯關係@ManyToMany

package com.jpa.helloworld; 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
 
@Table(name="CATEGORYS")
@Entity
public class Category { 
	private Integer cID; 
	private String cName; 
	private Set<Item> items = new HashSet<Item>();
 
	@Id
	@Column(name="C_ID")
	@GeneratedValue
	public Integer getcID() {
		return cID;
	}
 
	public void setcID(Integer cID) {
		this.cID = cID;
	}
 
	@Column(name="C_NAME")
	public String getcName() {
		return cName;
	}
 
	public void setcName(String cName) {
		this.cName = cName;
	}
	
	//新增了mappedBy屬性則不能使用@JoinTable註解
	@ManyToMany(mappedBy="categorys")
	public Set<Item> getItems() {
		return items;
	}
 
	public void setItems(Set<Item> items) {
		this.items = items;
	} 
}
package com.jpa.helloworld; 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
 
@Table(name="ITEMS")
@Entity
public class Item { 
	private Integer iId; 
	private String iName; 
	private Set<Category> categorys = new HashSet<Category>();
 
	@Id
	@GeneratedValue
	@Column(name="I_ID")
	public Integer getiId() {
		return iId;
	}
 
	public void setiId(Integer iId) {
		this.iId = iId;
	}
 
	@Column(name="I_NAME")
	public String getiName() {
		return iName;
	}
 
	public void setiName(String iName) {
		this.iName = iName;
	}
 
	//使用@JoinTable註解新增中間表
	//其中name屬性設定中間表的表名
	//joinCloums屬性在中間表中新增的列
	//JoinColumns屬性:
	//				@joinColumn屬性設定中間表中的列名
	//						referencedColumnName屬性指向被對映表的主鍵(可以沒有該屬性)
	//@inverseJoinColumns另外一張表在中間表中的列
	@JoinTable(
			name="ITEMS_CATEGORYS",
//			joinColumns = {@JoinColumn(name="ITEM_ID",referencedColumnName="I_ID")},
			joinColumns = {@JoinColumn(name="ITEM_ID")},
//			inverseJoinColumns= {@JoinColumn(name="CATEGORY_ID", referencedColumnName="C_ID")})
			inverseJoinColumns= {@JoinColumn(name="CATEGORY_ID")})
	@ManyToMany
	public Set<Category> getCategorys() {
		return categorys;
	}
 
	public void setCategorys(Set<Category> categorys) {
		this.categorys = categorys;
	} 
}

ManyToMany和OneToMany的雙向控制

下面我們使用許可權管理中Role<->Account(使用者ManyToMany賬號)、Role<->Domain(使用者OneToMany許可權域)的關係來舉例。  

1、ManyToMany

Role表

Account表

在兩個表的對應屬性上新增JoinColumns和inverseJoinColumns,並且相互交換。

  • JoinColumn指定本表在中間表中的列名。
  • inverseJoinColumns指定受控方的列名。

在兩個類中都加上這兩個屬性,並且值互換,則能夠實現雙向控制,即任何一方刪除,都會自動刪除對應中間表的資料。

2、OneToMany以及ManyToOne

Role表

Domain表

cascade用來指定級聯操作, cascade的值只能從CascadeType.PERSIST(級聯新建)、CascadeType.REMOVE(級聯刪  除)、CascadeType.REFRESH(級聯重新整理)、CascadeType.MERGE(級聯更新)中選擇一個或多個。還有一個選擇是使用CascadeType.ALL,表示選擇全部四項。

如果不指定Cascade,預設是空的,那麼在刪除Role的時候,只會把Domain表中的role這一列的值刪除,而該條記錄不刪除。

JoinColumn需要指定,如果不指定就會在Domain表中增加額外的一列,這一列與Domain的id一樣。經過試驗,不指定還會造成級聯查詢失敗,原因未知。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com