【问题标题】:Spring Jpa - Records deleted and re-inserted upon addition/deletion in join tableSpring Jpa - 在连接表中添加/删除时删除并重新插入的记录
【发布时间】:2021-03-17 04:08:27
【问题描述】:

我有 3 个实体 user、role 和 user_roles。

UserRole 实体与作为连接表的UserRoles 实体具有一对多的关系。我已将 user_roles 添加为实体,因为我们计划在未来将其他属性作为连接表的一部分。

用户实体

@Entity
@Table(name = "users")
public class User
{
    @Id
    @Column(name = "user_id")
    @GeneratedValue(generator = RandomIdGenerator.GENERATOR_NAME)
    @GenericGenerator(name = RandomIdGenerator.GENERATOR_NAME, strategy = "com.cs.util.RandomIdGenerator")
    private Long id;

    @Column(name = "email", nullable = false)
    private String email;

    @Column(name = "first_name", nullable = false)
    private String firstName;

    @Column(name = "last_name", nullable = false)
    private String lastName;

    @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER,mappedBy = "user", orphanRemoval = true)
    private List<UserRole> userRoles = new ArrayList<UserRole> ();

    @JsonSerialize(using = ToStringSerializer.class)
    public Long getId ()
    {
        return id;
    }
    public void setId (Long id)
    {
        this.id = id;
    }

    public String getEmail()
    {
        return email;
    }
    public void setEmail (String email)
    {
        this.email = email;
    }

    public String getFirstName()
    {
        return firstName;
    }
    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }

    public String getLastName()
    {
        return lastName;
    }
    public void setLastName(String lastName)
    {
        this.lastName = lastName;
    }

    @Transient
    public Set<Role> getRoles()
    {
        Set<Role> roles = new HashSet<Role> ();
        for (UserRole userRole : this.userRoles)
        {
            roles.add (userRole.getRole ());
        }
        return roles;
    }

    @JsonIgnore
    public List<UserRole> getUserRoles()
    {
        return userRoles;
    }
}

角色实体

@Entity
@Table(name="roles")
public class Role {

    @Id
    @Column(name = "role_id")
    @GeneratedValue(generator = RandomIdGenerator.GENERATOR_NAME)
    @GenericGenerator(name = RandomIdGenerator.GENERATOR_NAME, strategy = "com.cs.util.RandomIdGenerator")
    private Long id;

    @Column(name="name", nullable = false)
    private String name;
    
    @Column(name="description", nullable = true)
    private String description;
    
    @Column(name = "suspend_flag")
    private int suspendFlag;

    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(name = "roles_permission",
            joinColumns = @JoinColumn(name = "role_id"),
            inverseJoinColumns = @JoinColumn(name = "permission_id"))
    private Set<Permission> permissions= new HashSet<>();
    
    @OneToMany(mappedBy = "role")
    private List<UserRole> userRoles = new ArrayList<UserRole>();

    @JsonSerialize(using=ToStringSerializer.class)
    public Long getId ()
    {
        return id;
    }
    public void setId (Long id)
    {
        this.id = id;
    }

    public String getName ()
    {
        return name;
    }
    public void setName (String name)
    {
        this.name = name;
    }

    public String getDescription ()
    {
        return description;
    }
    public void setDescription (String description)
    {
        this.description = description;
    }

    public Set<Permission> getPermissions ()
    {
        return permissions;
    }

    public int getSuspendFlag ()
    {
        return suspendFlag;
    }
    public void setSuspendFlag (int suspendFlag)
    {
        this.suspendFlag = suspendFlag;
    }
}

用户角色实体

@Entity
@Table(name = "user_roles")
public class UserRole
{
    public UserRole ()
    {
    }
    
    public UserRole (User user, Role role)
    {
        this.user = user;
        this.role = role;
    }

    @Id
    @Column(name = "user_role_id")
    @GeneratedValue(generator = RandomIdGenerator.GENERATOR_NAME)
    @GenericGenerator(name = RandomIdGenerator.GENERATOR_NAME, strategy = "com.cs.util.RandomIdGenerator")
    private Long      id;
    
    @ManyToOne
    @JoinColumn(name = "user_id", referencedColumnName = "user_id")
    private User user;

    @ManyToOne
    @JoinColumn(name = "role_id", referencedColumnName = "role_id")
    private Role role;

    public Long getId ()
    {
        return id;
    }
    public void setId (Long id)
    {
        this.id = id;
    }
    
    @JsonIgnore
    public User getUser ()
    {
        return user;
    }
    public void setUser (User user)
    {
        this.user = user;
    }

    public Role getRole ()
    {
        return role;
    }
    public void setRole (Role role)
    {
        this.role = role;
    }
}

使用上面的代码一切正常,但是每当我插入或删除user_role 时,user_role 表中的所有记录都会被删除并重新插入。

例如,当我将一个新的 user_role 关联到一个用户时,现有的 user_role 会先被删除,然后它会与新的用户角色一起再次重新关联。

Hibernate: delete from user_roles where user_role_id=?
Hibernate: insert into user_roles (role_id, user_id, user_role_id) values (?, ?, ?)
Hibernate: insert into user_roles (role_id, user_id, user_role_id) values (?, ?, ?)

这就是我向用户实体添加用户角色的方式。

UserRole userRole = new UserRole(user,role);
user.getUserRoles ().add (userRole);
m_userRepository.save (_user)

然后像下面这样从用户中删除用户角色

List<UserRole> uRolesTobeRemoved = new ArrayList<UserRole> ();
for(Role role : userRoles)
{
    UserRole uRole = user.getUserRoles ().stream ().filter (userRole -> 
    userRole.getRole ().getId () == role.getId ()).collect (Collectors.toList ()).get (0);
    uRolesTobeRemoved.add (uRole);
}
user.getUserRoles ().removeAll (uRolesTobeRemoved);

我不确定缺少什么。

【问题讨论】:

  • whenever I insert or delete a user_role - 请说明您是如何删除或插入user_role
  • @SternK 我已经更新了我的问题,在末尾包含插入和删除逻辑。

标签: spring-boot hibernate spring-data-jpa


【解决方案1】:

您看到这种行为似乎是由于所谓的“收集娱乐”。 尝试将List&lt;UserRole&gt; userRoles 替换为Set&lt;UserRole&gt; userRoles。 更详细的解释你可以找到here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    • 2013-07-04
    相关资源
    最近更新 更多