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

淡淡的烟草味﹌ 2022-07-21 01:17 241阅读 0赞

双向N-N关联

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

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

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

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

Person实体类:

  1. package com.anlw.entity;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. import javax.persistence.Column;
  5. import javax.persistence.Entity;
  6. import javax.persistence.GeneratedValue;
  7. import javax.persistence.GenerationType;
  8. import javax.persistence.Id;
  9. import javax.persistence.JoinColumn;
  10. import javax.persistence.JoinTable;
  11. import javax.persistence.ManyToMany;
  12. import javax.persistence.Table;
  13. @Entity
  14. @Table(name = "person_inf")
  15. public class Person {
  16. // 标识属性
  17. @Id
  18. @Column(name = "person_id12")
  19. @GeneratedValue(strategy = GenerationType.IDENTITY)
  20. private Integer id;
  21. private String name;
  22. private int age;
  23. // 定义该Person实体所有关联的Address实体
  24. @ManyToMany(targetEntity = Address.class)
  25. // 应映射连接表,指定连接表为p_a
  26. @JoinTable(name = "p_a",
  27. // 映射连接表中名为person_id的外键列
  28. // 该列参照当前实体对应数据表的person_id主键列
  29. joinColumns = @JoinColumn(name = "person_id", referencedColumnName = "person_id12"),
  30. // 指定连接表中address_id列参照当前实体的关联实体对应数据表的address_id主键列
  31. inverseJoinColumns = @JoinColumn(name = "address_id", referencedColumnName = "address_id"))
  32. private Set<Address> addresses = new HashSet<Address>();
  33. public Integer getId() {
  34. return id;
  35. }
  36. public void setId(Integer id) {
  37. this.id = id;
  38. }
  39. public String getName() {
  40. return name;
  41. }
  42. public void setName(String name) {
  43. this.name = name;
  44. }
  45. public int getAge() {
  46. return age;
  47. }
  48. public void setAge(int age) {
  49. this.age = age;
  50. }
  51. public Set<Address> getAddresses() {
  52. return addresses;
  53. }
  54. public void setAddresses(Set<Address> addresses) {
  55. this.addresses = addresses;
  56. }
  57. }

上面程序中的注解代码映射了底层连接表的表名为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实体类:

  1. package com.anlw.entity;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. import javax.persistence.Column;
  5. import javax.persistence.Entity;
  6. import javax.persistence.GeneratedValue;
  7. import javax.persistence.GenerationType;
  8. import javax.persistence.Id;
  9. import javax.persistence.JoinColumn;
  10. import javax.persistence.JoinTable;
  11. import javax.persistence.ManyToMany;
  12. import javax.persistence.Table;
  13. @Entity
  14. @Table(name = "address_inf")
  15. public class Address {
  16. // 标识属性
  17. @Id
  18. @Column(name = "address_id")
  19. @GeneratedValue(strategy = GenerationType.IDENTITY)
  20. private int addressId;
  21. // 定义地址详细的成员变量
  22. private String addressDetail;
  23. // 定义该Address实体关联的Person实体
  24. @ManyToMany(targetEntity = Person.class)
  25. // 应映射连接表,指定连接表为p_a
  26. @JoinTable(name = "p_a",
  27. // 映射连接表中名为address_id的外键列
  28. // 该列参照当前实体对应数据表的address_id主键列
  29. joinColumns = @JoinColumn(name = "address_id", referencedColumnName = "address_id"),
  30. // 指定连接表中person_id列参照当前实体的关联实体对应数据表的person_id主键列
  31. inverseJoinColumns = @JoinColumn(name = "person_id", referencedColumnName = "person_id"))
  32. private Set<Person> person = new HashSet<Person>();
  33. public Address() {
  34. }
  35. public Address(String addressDetail) {
  36. this.addressDetail = addressDetail;
  37. }
  38. public int getAddressId() {
  39. return addressId;
  40. }
  41. public void setAddressId(int addressId) {
  42. this.addressId = addressId;
  43. }
  44. public String getAddressDetail() {
  45. return addressDetail;
  46. }
  47. public void setAddressDetail(String addressDetail) {
  48. this.addressDetail = addressDetail;
  49. }
  50. public Set<Person> getPerson() {
  51. return person;
  52. }
  53. public void setPerson(Set<Person> person) {
  54. this.person = person;
  55. }
  56. }

如果程序需要让双向N-N关联的两端都能控制关联关系,那么关联关系的两端都要增加@JoinTable映射连接表,而且两端映射的连接表的表明要相同,连接表中的数据列要相互对应;

发表评论

表情:
评论列表 (有 0 条评论,241人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Hibernate--关联映射

           hibernate是持久层ORM框架,关系映射解决了对象型实体与关系型数据库不相匹配的问题,它是Hibernate的核心内容,在实际操作中我们必须要根据数据表的相