如果孩子为空,休眠ManyToMany删除另一边

Posted

技术标签:

【中文标题】如果孩子为空,休眠ManyToMany删除另一边【英文标题】:Hibernate ManyToMany remove other side if children empty 【发布时间】:2021-10-24 04:03:26 【问题描述】:

我有 2 个具有 @ManyToMany 关系的实体。如果users 字段为空,我想在删除User 的同时删除Activity

@Entity
public class User 
...
@ManyToMany(mappedBy="users")
private List<Activity> activities;

@Entity
public class Activity 

@ManyToMany(cascade = CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH)
@JoinTable(name = "USER_ACTIVITY",
           joinColumns = @JoinColumn(name = "ACTIVITY_ID"),
           inverseJoinColumns = @JoinColumn(name = "USER_ID"))
private List<User> users;

例如删除前有以下记录

USERS
id    name
----+-------
1     user1
2     user2
3     user3

ACTIVITY
id    name
----+-------
1     act1
2     act2
3     act3

USER_ACTIVITY
USER_ID    ACTIVITY_ID
---------+-------
1          1
2          1
2          2
3          1
3          3
2          3
1          3

如果user2 被删除,那么act2 也应该被删除。因为它没有更多的用户。所以删除 user2 后的记录应该如下所示:

USERS
id    name
----+-------
1     user1
3     user3

ACTIVITY
id    name
----+-------
1     act1
3     act3

USER_ACTIVITY
USER_ID    ACTIVITY_ID
---------+-------
1          1
3          1
3          3
1          3

【问题讨论】:

【参考方案1】:

您必须反转映射并像这样使用CascadeType.ALL

@Entity
public class User 
...
  @ManyToMany(cascade = CascadeType.ALL)
  @JoinTable(name = "USER_ACTIVITY",
           joinColumns = @JoinColumn(name = "USER_ID"),
           inverseJoinColumns = @JoinColumn(name = "ACTIVITY_ID"))
  private List<Activity> activities;


@Entity
public class Activity 

  @ManyToMany(mappedBy="activities")
  private List<User> users;

【讨论】:

以上是关于如果孩子为空,休眠ManyToMany删除另一边的主要内容,如果未能解决你的问题,请参考以下文章

休眠 Spring:@ManyToMany DataIntegrityViolationException ConstraintViolationException

删除实体时休眠将外键设置为空

Doctrine2 ManyToMany 自引用

休眠 - 多对多关系中的级联删除

注释 ConcurrentHashMap 时,在休眠中“非法尝试将非集合映射为 @OneToMany、@ManyToMany 或 @CollectionOfElements”

如果另一个字段为空,则将字段更新为空或删除行