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
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流烟默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值