Hibernate的关联映射(7)-双向1-1关联

来源:互联网 发布:charles mac 编辑:程序博客网 时间:2024/05/21 14:45

双向1-1关联

双向1-1关联需要修改两端的持久化代码,让两个持久化类都增加引用关联实体的属性,并为该属性提供setter和getter方法;

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1>基于外键的双向1-1关联1

对于双向1-1关联而言,两端都需要使用@OneToOne注解进行映射;

对于基于外键的双向1-1关联,外键可以存放在任意一端,存放外键的一端,需要增加@joinColumn注解来映射外键列,与前面介绍相同的是,还应该为@JoinColumn注解增加uniique=true属性来表示该实体实际上是1的一端;

对于1-1的关联关系,两个实体原本处于平等状态,但当选择任意一端来增加外键后,(增加@JoinColumn注解的实体端),该表即变成从表,而另一个表则成为主表;

对于双向1-1关联的主表对应的实体,也不应该控制关联关系,(否则会导致生成额外的update语句,从而引起性能下降),因此主表对应的实体中使用@OneToOne注解时,应该增加@mappedBy属性,该属性用于表明该实体不管理关联关系,这一端对应的数据表将作为主表使用,不能使用@JoinColumn映射外键列;

下面是双向1-1关联的主表一端,使用@OneToOne时增加了mappedBy属性,没有使用@JoinColumn注解修饰代表关联实体的属性:

<span style="font-size:18px;">package com.anlw.entity;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.OneToOne;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实体@OneToOne(targetEntity = Address.class,mappedBy="person")private Address 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 Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}}</span>
上面注解@OneToOne映射指定了mappedBy属性,表明该Perosn实体不再控制关联关系;

下面是双向1-1关联从表的一端,使用@OneToOne时不指定mappedBy属性,需要使用@JoinColumn注解修饰代表关联实体的属性,用于显式定义外键列;

<span style="font-size:18px;">package com.anlw.entity;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.OneToOne;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实体@OneToOne(targetEntity = Person.class)// 用于映射person_id外键列,参照person_inf表的person_id列// 指定了unique=true表明是1-1关联@JoinColumn(name = "person_id", referencedColumnName = "person_id12", unique = true)private Person person;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 Person getPerson() {return person;}public void setPerson(Person person) {this.person = person;}}</span>

上面的@JoinColumn注解显式的映射了底层的外键列,并指定unique=true,这代表了1-1关联;

上面的映射策略可以互换,即让Person端存放外键,使用@JoinColumn注解映射关联属性,但Address端则使用@OneToOne时增加mappedBy属性,但不要两端都使用相同的注解进行映射;

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2>有连接表的双向1-1关联

采用连接表的双向1-1关联是相当罕见的情形,映射相当复杂,数据模型繁琐,通常不推荐使用这种策略;

有连接表的双向1-1关联需要在两端分别使用@OneToOne修饰代表关联实体的属性,并在两端都使用@JoinTable显式的映射连接表,在映射连接表时,两端指定的连接表的表名应该相同,而且两端使用@JoinTable时指定的外键列的列名也是相互对应的;

需要说明的是,如果程序希望某一端放弃控制关联关系,则可在这一端的@OneToOne注解中指定mappedBy属性,这一端就无须也不能使用@JoinTable映射连接表了,由于此时是1-1关联,因此使用@JoinTable注解时指定的@JoinColumn都需要增加unique=true;

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

下面是双向1-1关联的Person实体类的代码,程序使用了@JoinTable和@OneToOne修饰代表关联实体的属性:

<span style="font-size:18px;">package com.anlw.entity;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.OneToOne;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实体@OneToOne(targetEntity = Address.class)//映射底层连接表,表明为p_a@JoinTable(name="p_a",//映射连接表的外键列,增加unique=true表明是1-1关联joinColumns=@JoinColumn(name="person_id",referencedColumnName="person_id12",unique=true),//映射连接表的外键列,增加unique=true表明是1-1关联inverseJoinColumns=@JoinColumn(name="address_id",referencedColumnName="address_id",unique=true))private Address 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 Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}}</span>
下面是双向1-1关联的Address实体类代码,程序通常使用@JoinTable和@OneToOne修饰代表关联实体的属性:
<span style="font-size:18px;">package com.anlw.entity;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.OneToOne;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实体@OneToOne(targetEntity = Person.class)// 映射底层连接表,表明为p_a@JoinTable(name = "p_a",// 映射连接表的外键列,增加unique=true表明是1-1关联joinColumns = @JoinColumn(name = "address_id", referencedColumnName = "address_id", unique = true),// 映射连接表的外键列,增加unique=true表明是1-1关联inverseJoinColumns = @JoinColumn(name = "person_id", referencedColumnName = "person_id12", unique = true))private Person person;public Address(){}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 Person getPerson() {return person;}public void setPerson(Person person) {this.person = person;}}</span>
从上面的两个关联实体的注解来看,他们双方所使用的注解是对等的,他们双方映射的表名是相同的,映射连接表中的外键列也是相互对应的,因此这两个实体都可用于控制关系,并且双方的地位是绝对平等的;

0 0
原创粉丝点击