JPA - 双向多对多映射

简介: JPA - 双向多对多映射

在双向多对多关系中,我们必须指定一个关系维护端(owner side),可以通过 @ManyToMany 注释中指定 mappedBy 属性来标识其为关系维护端。

如下所示,为Category类片段:

@ManyToMany(mappedBy="categories")
public Set<Item> getItems() {
  return items;
}

这样解释mappedBy:

  • 在哪个model中的某个注解使用了mappedBy,则该model放弃维持关联关系;如上所示,这里为Category放弃维持关联关系,以Item为主;
  • 在哪个属性上面的注解使用了mappedBy属性,则该注解标注的属性的实体类维持关联关系。如上所示,这里以Item为主。

【1】item与Category

item:category = N:N ,item为关系维护端(主),category为从。

item类如下:

@Table(name="JPA_ITEMS")
@Entity
public class Item {
  private Integer id;
  private String itemName;
  private Set<Category> categories = new HashSet<>();
  @GeneratedValue
  @Id
  public Integer getId() {
    return id;
  }
  public void setId(Integer id) {
    this.id = id;
  }
  @Column(name="ITEM_NAME")
  public String getItemName() {
    return itemName;
  }
  public void setItemName(String itemName) {
    this.itemName = itemName;
  }
  //使用 @ManyToMany 注解来映射多对多关联关系
  //使用 @JoinTable 来映射中间表
  //1. name 指向中间表的名字
  //2. joinColumns 映射当前类所在的表在中间表中的外键
  //2.1 name 指定外键列的列名
  //2.2 referencedColumnName 指定外键列关联当前表的哪一列
  //3. inverseJoinColumns 映射关联的类所在中间表的外键
  @JoinTable(name="ITEM_CATEGORY",
      joinColumns={@JoinColumn(name="ITEM_ID", referencedColumnName="ID")},
      inverseJoinColumns={@JoinColumn(name="CATEGORY_ID", referencedColumnName="ID")})
  @ManyToMany
  public Set<Category> getCategories() {
    return categories;
  }
  public void setCategories(Set<Category> categories) {
    this.categories = categories;
  }
}

category类如下:

@Table(name="JPA_CATEGORIES")
@Entity
public class Category {
  private Integer id;
  private String categoryName;
  private Set<Item> items = new HashSet<>();
  @GeneratedValue
  @Id
  public Integer getId() {
    return id;
  }
  public void setId(Integer id) {
    this.id = id;
  }
  @Column(name="CATEGORY_NAME")
  public String getCategoryName() {
    return categoryName;
  }
  public void setCategoryName(String categoryName) {
    this.categoryName = categoryName;
  }
  @ManyToMany(mappedBy="categories")
  public Set<Item> getItems() {
    return items;
  }
  public void setItems(Set<Item> items) {
    this.items = items;
  }
}

【2】多对多持久化操作

示例代码如下:

//多对多的保存
  @Test
  public void testManyToManyPersist(){
    Item i1 = new Item();
    i1.setItemName("i-1");
    Item i2 = new Item();
    i2.setItemName("i-2");
    Category c1 = new Category();
    c1.setCategoryName("C-1");
    Category c2 = new Category();
    c2.setCategoryName("C-2");
    //设置关联关系
    i1.getCategories().add(c1);
    i1.getCategories().add(c2);
    i2.getCategories().add(c1);
    i2.getCategories().add(c2);
    c1.getItems().add(i1);
    c1.getItems().add(i2);
    c2.getItems().add(i1);
    c2.getItems().add(i2);
    //执行保存
    entityManager.persist(i1);
    entityManager.persist(i2);
    entityManager.persist(c1);
    entityManager.persist(c2);
  }

控制台输出如下:

Hibernate: 
    insert 
    into
        JPA_ITEMS
        (ITEM_NAME) 
    values
        (?)
Hibernate: 
    insert 
    into
        JPA_ITEMS
        (ITEM_NAME) 
    values
        (?)
Hibernate: 
    insert 
    into
        JPA_CATEGORIES
        (CATEGORY_NAME) 
    values
        (?)
Hibernate: 
    insert 
    into
        JPA_CATEGORIES
        (CATEGORY_NAME) 
    values
        (?)
Hibernate: 
    insert 
    into
        ITEM_CATEGORY
        (ITEM_ID, CATEGORY_ID) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        ITEM_CATEGORY
        (ITEM_ID, CATEGORY_ID) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        ITEM_CATEGORY
        (ITEM_ID, CATEGORY_ID) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        ITEM_CATEGORY
        (ITEM_ID, CATEGORY_ID) 
    values
        (?, ?)

数据库结果如下:


【3】双向多对多获取操作

先获取非维护关联关系的一方,代码示例如下:

  @Test
  public void testManyToManyFind(){
    Category category = entityManager.find(Category.class, 3);
    System.out.println(category.getCategoryName());
    System.out.println(category.getItems().size());
  }

控制台输出如下:



如果先获取维护关联关系的一方呢?

示例代码如下:

  @Test
  public void testManyToManyFind(){
      Item item = entityManager.find(Item.class, 5);
      System.out.println(item.getItemName());
      System.out.println(item.getCategories().size());
  }

控制台输出如下:


故而总结如下:


对于关联的集合对象, 默认使用懒加载的策略;


使用维护关联关系的一方获取, 还是使用不维护关联关系的一方获取, SQL 语句相同。


目录
相关文章
|
1月前
|
SQL Java
JPA - 双向多对一映射
JPA - 双向多对一映射
41 2
|
1月前
|
SQL Java 数据库
JPA - 单向一对多映射
JPA - 单向一对多映射
38 2
|
1月前
|
SQL Java
JPA - 双向1对1映射
JPA - 双向1对1映射
34 2
|
1月前
|
SQL 缓存 Java
Hibernae - 双向多对一关联关系映射
Hibernae - 双向多对一关联关系映射
38 0
|
1月前
|
Java uml
JPA - 单向多对一映射
JPA - 单向多对一映射
46 0
|
11月前
|
SQL XML Java
Hibernate框架【四】——基本映射——多对一和一对多映射
Hibernate框架【四】——基本映射——多对一和一对多映射
119 0
|
存储 Java 数据库连接
Hibernate的一对多映射的单向关联和双向关联(九)
Hibernate的一对多映射的单向关联和双向关联(九)
121 0
Hibernate的一对多映射的单向关联和双向关联(九)
|
SQL Oracle Java
hibernate(四) 双向多对多映射关系
现在继上一章节的一对多的映射关系讲解后,今天来讲讲多对多的映射关系把,明白了一对多,多对多个人感觉还是比较容易的,需要理清楚其数据库关系图,那么你就拿下了它。映射文件的配置还是那么些死东西。
141 0