七、关联映射
关联映射
1.单向N-1关联
2.单向1-1关联
3.单向1-N关联
(1)单向1-N关联与集合属性相似,只是在1-N关联时集合中的元素为关联实体;
(2)使用注解@OneToMany;
(3)无连接表的单向1-N关联
示例:
1的一端Person3:
@Entity @Table(name="person_inf_4") public class Person3 { @Id @Column(name="person_id") @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String name; private Integer age; @OneToMany(targetEntity=Address3.class) @JoinColumn(name="person_id",referencedColumnName="person_id") private Set<Address3> addresses = new HashSet<>(); 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 Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Set<Address3> getAddresses() { return addresses; } public void setAddresses(Set<Address3> addresses) { this.addresses = addresses; } }
N的一段Address3:
@Entity @Table(name="address_inf_4") public class Address3 { @Id @Column(name="address_id") @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer addressId; private String addressDetail; public Address3(){ } public Address3(String addressDetail){ this.addressDetail = addressDetail; } public Integer getAddressId() { return addressId; } public void setAddressId(Integer addressId) { this.addressId = addressId; } public String getAddressDetail() { return addressDetail; } public void setAddressDetail(String addressDetail) { this.addressDetail = addressDetail; } }
测试:
public class Test { public static void main(String[] args) { Configuration conf = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(conf.getProperties()).build(); SessionFactory sessionFactory = conf.buildSessionFactory(serviceRegistry); Session session = sessionFactory.openSession(); Transaction t = session.beginTransaction(); //创建一个Person对象 Person3 p = new Person3(); //创建一个瞬态的Address对象 Address3 address = new Address3("地址1"); //必须先持久化address session.persist(address); //与save()区别:无返回值 //设置p的属性 p.setName("name1"); p.setAge(18); //设置p和address之间的关联关系 p.getAddresses().add(address); //持久化p对象 session.persist(p); //创建一个瞬态的Address Address3 address2 = new Address3("地址2"); //持久化address2对象 session.persist(address2); p.getAddresses().add(address2); t.commit(); session.close(); sessionFactory.close(); } }
(4)有连接表的单向1-N关联
有连接表的单向1-N关联除了使用@OneToMany以外,还要使用@JoinTable显式指定连接表。
对于采用连接表的单向1-N关联关系,由于采用了连接表维护1-N关系,两个实体对应的数据表都无须添加外键列,所以不存在主表和从表的关系,程序可以向先持久化那个实体就先持久化那个实体。无论先持久化哪个实体都不会引发性能问题。
示例:
Person4:
@Entity @Table(name="person_inf_5") public class Person4 { @Id @Column(name="person_id") @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String name; private Integer age; //定义该Person实体所有关联的Address实体 @OneToMany(targetEntity=Address4.class) //映射连接表为person_address @JoinTable(name="person_address", //定义链接表中名为person_id的外键列,该外键列参照当前实体对应表的主键列 joinColumns=@JoinColumn( name="person_id", referencedColumnName="person_id" ), //定义连接表中名为address_id的外键列 //该外键列参照当前实体的关联实体对应表的主键列 inverseJoinColumns=@JoinColumn( name="address_id", referencedColumnName="address_id", unique=true ) ) private Set<Address4> addresses = new HashSet<>(); 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 Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Set<Address4> getAddresses() { return addresses; } public void setAddresses(Set<Address4> addresses) { this.addresses = addresses; } }
Address4:
@Entity @Table(name="address_inf_5") public class Address4 { @Id @Column(name="address_id") @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer addressId; private String addressDetail; public Address4(){ } public Address4(String addressDetail){ this.addressDetail = addressDetail; } public Integer getAddressId() { return addressId; } public void setAddressId(Integer addressId) { this.addressId = addressId; } public String getAddressDetail() { return addressDetail; } public void setAddressDetail(String addressDetail) { this.addressDetail = addressDetail; } }
测试:
public class Test4 { public static void main(String[] args) { Configuration conf = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(conf.getProperties()).build(); SessionFactory sf = conf.buildSessionFactory(serviceRegistry); Session session = sf.openSession(); Transaction t = session.beginTransaction(); Address4 a = new Address4("地址1"); Address4 a2 = new Address4("地址2"); Address4 a3 = new Address4("地址3"); session.persist(a); session.persist(a2); session.persist(a3); Person4 p = new Person4(); p.setAge(18); p.setName("test1"); p.getAddresses().add(a); p.getAddresses().add(a2); p.getAddresses().add(a3); session.save(p); t.commit(); session.close(); sf.close(); } }
4.单向N-N关联
(1)单向N-N关联需要连接表,与使用连接表的1-N关联类似,只不过在管理关系的一端配置inverseJoinColumns参数时没有unique=true这一项,就成为了单向的N-N关联;
(2)示例:
Person(管理关联关系):
@Entity @Table(name="person_inf_1") public class Person { @Id @Column(name="person_id") @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String name; private Integer age; @ManyToMany(targetEntity=Address.class) @JoinTable( name="person_address", joinColumns=@JoinColumn( name="person_id", referencedColumnName="person_id" ), inverseJoinColumns=@JoinColumn( name="address_id", referencedColumnName="address_id" ) ) private Set<Address> addresses = new HashSet<>(); 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 Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Set<Address> getAddresses() { return addresses; } public void setAddresses(Set<Address> addresses) { this.addresses = addresses; } }
Address:
@Entity @Table(name="address_inf_1") public class Address { @Id @Column(name="address_id") @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String addressDetail; public Address(){ } public Address(String addressDetail){ this.addressDetail = addressDetail; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getAddressDetail() { return addressDetail; } public void setAddressDetail(String addressDetail) { this.addressDetail = addressDetail; } }
5.双向1-N关联
6.双向N-N关联
7.双向1-1关联
8.组件属性包含的关联实体
9.基于复合主键的关联关系
10.复合主键的成员属性为关联实体
11.持久化的传播性