解决hibernate更新中间表时,会先删除再更新的问题

问题:如题,hibernate在更新中间表时,会先删除旧的数据再插入新数据的问题。
情景:比如现在数据库有一张user表,一张role表,一张user_role中间表


image.png

image.png

image.png
  • User实体类
@Data
@Entity
@Table(name = "user")
public class User implements Serializable {
    private static final long serialVersionUID = -6325275400468409210L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Expose
    private long id;
    @JsonIgnore
    @Column
    private String uid;
    @Column
    @Expose
    private String phone;
    @Column
    @Expose
    private String email;
    @Column
    @JsonIgnore
    private String password;
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    @Expose
    private List<Role> roles;
  • 测试:当user有角色“ROLE_USER_NORMAL”的前提下,想给user在添加一个角色“ROLE_USER_ADMIN”,这是会出现user_role表中id为1的数据被删除,然后添加了两条新数据,id分别为2和3,其中id为2的数据和被删除的id为1的数据相同。
@Test
public void testAddRoleForUser() throws Exception {
    User user = userRepository.findByPhone("183xxxxxxxx");
    Role role = roleRepository.findByName("ROLE_USER_ADMIN");
    user.getRoles().add(role);
    userRepository.save(user);
}
  • 解决:
    1、将List<Role> roles改为Set<Role> roles。
    2、重写主表实体类的equals()和hasCode()方法。
@Data
@Entity
@Table(name = "user")
public class User implements Serializable {
    private static final long serialVersionUID = -6325275400468409210L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Expose
    private long id;
    @JsonIgnore
    @Column
    private String uid;
    @Column
    @Expose
    private String phone;
    @Column
    @Expose
    private String email;
    @Column
    @JsonIgnore
    private String password;
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    @Expose
    private Set<Role> roles;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        return false;
    }

    @Override
    public int hashCode() {
        int result = 20;
        result = (int) (result * 31 + id);
        result = result * 31 + uid.hashCode();
        result = result * 31 + phone.hashCode();
        result = result * 31 + email.hashCode();
        result = result * 31 + password.hashCode();
        return result;
    }

此时再测试时,将不会删除id为1的数据,而是直接添加id为2的新数据。
再来测试一下从两个角色中删除“ROLE_USER_ADMIN”这个角色。

@Test
public void testDeleteRoleFromUser() throws Exception {
    User user = userRepository.findByPhone("18349178884");
    Set<Role> roles = user.getRoles();
    Iterator<Role> it = roles.iterator();
    //roles.removeIf(role1 -> role1.getName().equals("ROLE_USER_ADMIN")); 等价于下面的while循环
    while (it.hasNext()) {
        Role role = it.next();
        if (role.getName().equals("ROLE_USER_ADMIN")) {
            it.remove();
        }
    }
    log.info("roles: {}", roles);
    userRepository.save(user);
}

成功!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容