Hibernate @ManyToMany delete relation

场景

假设有俩个实体用户和专业课(关系:多对多)git

现需求用户能够新增编辑专业课,但在专业课模块中一样能够新增用户和编辑用户github

实体

Course:数据库

@Entity
public class Course implements YunzhiEntity {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToMany(mappedBy = "courses")
    private List<User> users;
    
    public Course() {}
}

User:app

@Entity

public class User implements YunzhiEntity {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)

    private Long id;

    private String name;

    @Column(nullable = false, unique = true)
    private String username;

    @Column(nullable = false)
    private String password;

    @ManyToMany
    private List<Course> courses;

    public User() {}
}

最初实现

思路
新增:新增比较简单,直接操做中间表把数据保存到中间表
更新:更新变向的理解也就是新增,因此就先把原来的删除在新增

因为mappedBy映射关系是由一方维护,因此须要后台单独处理中间表中的数据测试

实现以下:
image.pngspa

在更新中把中间表相关数据先移出,而后在从新创建关系,以下:hibernate

image.png

将新的数据,保存到中间表中。在此使专业课和用户从新创建新的关系code

在新增时只需save时在调用updateUsersOfCourse(Course course)这个方法就能够blog

这种实现方式看起来比较笨拙,潘老师提示, Hibernate不会这么傻,须要这么麻烦,确定有新的实现方式

新的实现

使用Hibernate的关联删除,去除手动操做中间表的代码,看起来更简洁,更新更容易理解文档

image.png

修改实体 Course实体与User实体,不使用由一方维护的mappedBy来映射关系,以下:
Course:

@Entity  
public class Course implements YunzhiEntity {  
  
     ......
  
    @ManyToMany(cascade ={CascadeType.REMOVE})  
    @JoinTable(name="User_Courses",joinColumns=@JoinColumn(name="Courses_id"),inverseJoinColumns=@JoinColumn(name="Users_id"))  
    @JsonView(users.class)  
    private List<User> users;  
    
    ......
    
 }

User:

@Entity  
public class User implements YunzhiEntity {

    ......
    
    @ManyToMany(cascade ={CascadeType.REMOVE})  
    @JoinTable(name="User_Courses",joinColumns=@JoinColumn(name="Users_id"),inverseJoinColumns=@JoinColumn(name="Courses_id"))  
    @JsonView(courses.class)  
    private List<Course> courses;
    
    ......
    
}

使用mappedBy来创建俩实体间的关系,它是一方来维护的,就像 ‘A中有B或B中有A’,是单向的。因此直接使用cascade ={CascadeType.REMOVE}级联删除,很差使;

向上述例子,‘A中有B,B中有A’,是双向的。“双向结构+双向维护外键”。这个双向维护外键,指不管是对course.users仍是user.courses修改,保存后均会影响中间表的数据。

参考文档 stackoverflow

小测试

创建三个实体 A B C
A:B = ManyToMany(上述新方式)
A:C = ManyToMany(普通的方式mappedBy)

一样执行多对多的更新操做。对比两个更新最终生成的SQl语句有何不一样。

A:

image.png

B:

image.png

C:

image.png

源码地址 github

使用Postman向后台发送请求,执行更新操做,获得SQl语句,以下:

上述新方法生成的SQL语句:

image.png

普通的方式mappedBy生成的SQL语句:

image.png

发现普通的方式 mappedBy生成的 SQL语句比较多,多的是更新时操做中间表 SQL,为数据库增长了无形的压力。
相关文章
相关标签/搜索