Hibernate的关联映射(6)-双向N-N关联

双向N-N关联

双向N-N关联需要两端都使用Set集合属性,两端都增加对集合属性的访问;双向N-N关联没有太多选择,只能采用连接表来建立两个实体之间的关联关系;

双向N-N关联需要在两端分别使用@ManyToMany修饰Set集合属性,并在两端都使用@JoinTable显示映射连接表,在两端映射连接表时,两端指定的连接表的表名应该相同,而且两端使用@JoinTable时指定的外键列的列名也应是相互对应的;

需要说明的是,如果程序希望某一端放弃控制关联关系,则可以在这一端的@ManyToMany注解中指定mappedBy属性,这一端也就无需也不能使用@JoinTable映射连接表了;

下面的例子让Person实体类与Address实体类保留双向的N-N关联关系,而且双方都能控制关联关系,因此程序需要在两边分别使用@ManyToMany,@JoinTable映射连接表;

Person实体类:

package com.anlw.entity;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name = "person_inf")
public class Person {
	// 标识属性
	@Id
	@Column(name = "person_id12")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	private String name;
	private int age;
	// 定义该Person实体所有关联的Address实体
	@ManyToMany(targetEntity = Address.class)
	// 应映射连接表,指定连接表为p_a
	@JoinTable(name = "p_a",
			// 映射连接表中名为person_id的外键列
			// 该列参照当前实体对应数据表的person_id主键列
			joinColumns = @JoinColumn(name = "person_id", referencedColumnName = "person_id12"),
			// 指定连接表中address_id列参照当前实体的关联实体对应数据表的address_id主键列
			inverseJoinColumns = @JoinColumn(name = "address_id", referencedColumnName = "address_id"))
	private Set<Address> addresses = new HashSet<Address>();

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public Set<Address> getAddresses() {
		return addresses;
	}

	public void setAddresses(Set<Address> addresses) {
		this.addresses = addresses;
	}

}
上面程序中的注解代码映射了底层连接表的表名为p_a,并指定该连接表中包含两列:person_id,address_id,其中person_id参照person_inf表的person_id12主键列,address_id参照address_inf表的address_id主键列,由于此处管理的是N-N关联,因此不能为任何@JoinColumn注解增加unique=true;

接下来管理Address实体类时,应该让Address一端管理的连接表的表名也为p_a,且连接表中两列的列名分别为addrss_id和person_id;

Address实体类:

package com.anlw.entity;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name = "address_inf")
public class Address {
	// 标识属性
	@Id
	@Column(name = "address_id")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int addressId;
	// 定义地址详细的成员变量
	private String addressDetail;
	// 定义该Address实体关联的Person实体
	@ManyToMany(targetEntity = Person.class)
	// 应映射连接表,指定连接表为p_a
	@JoinTable(name = "p_a",
			// 映射连接表中名为address_id的外键列
			// 该列参照当前实体对应数据表的address_id主键列
			joinColumns = @JoinColumn(name = "address_id", referencedColumnName = "address_id"),
			// 指定连接表中person_id列参照当前实体的关联实体对应数据表的person_id主键列
			inverseJoinColumns = @JoinColumn(name = "person_id", referencedColumnName = "person_id"))
	private Set<Person> person = new HashSet<Person>();

	public Address() {
	}

	public Address(String addressDetail) {
		this.addressDetail = addressDetail;
	}

	public int getAddressId() {
		return addressId;
	}

	public void setAddressId(int addressId) {
		this.addressId = addressId;
	}

	public String getAddressDetail() {
		return addressDetail;
	}

	public void setAddressDetail(String addressDetail) {
		this.addressDetail = addressDetail;
	}

	public Set<Person> getPerson() {
		return person;
	}

	public void setPerson(Set<Person> person) {
		this.person = person;
	}
}
如果程序需要让双向N-N关联的两端都能控制关联关系,那么关联关系的两端都要增加@JoinTable映射连接表,而且两端映射的连接表的表明要相同,连接表中的数据列要相互对应;






















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值