双向关联
一 双向1--N关联
1.无连接表的双向1--N关联
N的一端需要使用@ManyToOne注解来修饰代表关联实体的属性,1的一端需要使用@OneToMany注解来修饰代表关联实体的属性。
双向关联应该由N的一端来控制关联关系,因此在使用@OneToMany注解时指定mappedBy属性。一旦为@OneToMany,@ManyToMany指定了该属性,则表明当前实体不能控制关联关系,一旦当前实体放弃控制关联关系后,hibernate就不允许使用@JoinColumn或@JoinTable修饰代表关联实体的属性了。
Person.java
@Entity
@Table(name="person_info")
public class Person {
@Id
@Column(name="person_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;
private int age;
@OneToMany(targetEntity=Address.class,mappedBy="person")
private Set<Address> addresses=new HashSet<>();
...
}
Address.java
@Entity
@Table(name="address_info")
public class Address {
@Id
@Column(name="address_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private int addressId;
private String adressDetail;
@ManyToOne(targetEntity=Person.class)
@JoinColumn(name="person_id",referencedColumnName="person_id",nullable=false)
private Person person;
...
}
测试:
public class myTest {
public static void main(String[] args) {
Configuration config=new Configuration().configure();
SessionFactory factory=config.buildSessionFactory();
Session session=factory.openSession();
Transaction tx=session.beginTransaction();
Person p=new Person();
p.setName("lyy");p.setAge(22);
session.save(p); //持久化person对象
Address a=new Address("北京");
a.setPerson(p); //设置person和address之间的关联关系
session.persist(a); //持久化address对象
Address a2=new Address("南京");
a2.setPerson(p);
session.persist(a2);
tx.commit();
session.close();
}
}
注意:最好先持久化Person对象或者该Person对象已经处于持久化状态,因为程序希望持久化Address对象时,Hibernate可以为Address的外键属性分配值。也就是说,向address_info数据表插入记录时,该记录的外键列已指定了值,着表明它参照的主表记录已存在。
不要通过Person对象来设置关联关系,因为在Person映射注解中指定了@mappedBy属性
2.有连接表的双向1--N关联
只要在N的一端使用@JoinTable显式指定连接表即可
Address.java
@Entity
@Table(name="address_info")
public class Address {
@Id
@Column(name="address_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private int addressId;
private String adressDetail;
@ManyToOne(targetEntity=Person.class)
@JoinTable(name="person_address",
[email protected](name="address_id",referencedColumnName="address_id"),
[email protected](name="person_id",referencedColumnName="person_id"))
private Person person;
...
}
如果程序希望Person实体也可以控制关联关系,则可以将Person.java修改为:
@Entity
@Table(name="person_info")
public class Person {
@Id
@Column(name="person_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;
private int age;
@OneToMany(targetEntity=Address.class)
@JoinTable(name="person_address",
[email protected](name="person_id",referencedColumnName="person_id"),
[email protected](name="address_id",referencedColumnName="address_id",unique=true))
private Set<Address> addresses=new HashSet<>();
...
}
二 双向N--N关联
两端都需要使用Set集合属性,双向N--N关联只能采用连接表来建立两个实体间的关联关系
Person.java
@Entity
@Table(name="person_info")
public class Person {
@Id
@Column(name="person_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;
private int age;
@OneToMany(targetEntity=Address.class)
@JoinTable(name="person_address",
[email protected](name="person_id",referencedColumnName="person_id"),
[email protected](name="address_id",referencedColumnName="address_id",unique=true))
private Set<Address> addresses=new HashSet<>();
...
}
Address.java
@Entity
@Table(name="address_info")
public class Address {
@Id
@Column(name="address_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private int addressId;
private String adressDetail;
@ManyToOne(targetEntity=Person.class)
@JoinTable(name="person_address",
[email protected](name="address_id",referencedColumnName="address_id"),
[email protected](name="person_id",referencedColumnName="person_id"))
private Person person;
...
}
三 双向1--1关联
两端都要使用@OneToOne注解进行映射,外键可以存放在任意一端,即通过@JoinColumn注解来映射外键列。一旦选择其中的一端来增加外键,该表即变为从表,另一个表则为主表。
双向1--1关联的主表对应的实体,也不应该用于控制关联关系,因此要用mappedBy属性
1.基于外键的双向1--1关联
Person.java
@Entity
@Table(name="person_info")
public class Person {
@Id
@Column(name="person_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;
private int age;
@OneToOne(targetEntity=Address.class,mappedBy="person")
private Address address;
...
}
Address.java
@Entity
@Table(name="address_info")
public class Address {
@Id
@Column(name="address_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private int addressId;
private String adressDetail;
@OneToOne(targetEntity=Person.class)
@JoinColumn(name="person_id",referencedColumnName="person_id",unique=true)
...
}
测试:
public class myTest {
public static void main(String[] args) {
Configuration config=new Configuration().configure();
SessionFactory factory=config.buildSessionFactory();
Session session=factory.openSession();
Transaction tx=session.beginTransaction();
Person p=new Person("lu",23);
Address a=new Address("nanjing");
p.setAddress(a);
session.save(p); session.save(a);
tx.commit();
session.close();
}
}