SpringBoot 2.0.4 中同一实体的多个表示

Posted

技术标签:

【中文标题】SpringBoot 2.0.4 中同一实体的多个表示【英文标题】:Multiple representations of the same entity in SpringBoot 2.0.4 【发布时间】:2019-01-31 21:54:36 【问题描述】:

我有一个基本的 SpringBoot 2.0.4.RELEASE 应用程序。使用 Spring Initializer、JPA、嵌入式 Tomcat、Thymeleaf 模板引擎,并打包为可执行 JAR 文件。

我有一个带有角色的用户对象:

@Entity
@Table(name="t_user")
public class User implements Serializable, UserDetails 


 @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
    @JoinTable(
        name="t_user_role",
        joinColumns=@JoinColumn(name="user_id", referencedColumnName="id"),
        inverseJoinColumns=@JoinColumn(name="role_id", referencedColumnName="id"))
    private Set<Role> roles = new HashSet<>();
..

当我启动应用程序时。我创建了所有角色:

roleService.save(new Role(RolesEnum.USER.getRoleName()));
roleService.save(new Role(RolesEnum.ADMIN.getRoleName()));

然后我创建一个具有 USER 角色的用户:

User user1 = new User();


         Role role = roleService.findByName(RolesEnum.USER.getRoleName());

         user.getRoles().add(role);
          userService.save(user);

但是当我创建另一个具有相同角色的用户时:

User user2 = new User();


         Role role = roleService.findByName(RolesEnum.USER.getRoleName());

         user2.getRoles().add(role);
          user2Service.save(user);

我收到了这个错误:

Multiple representations of the same entity [com.tdk.backend.persistence.domain.backend.Role#1] are being merged. Detached: [com.tdk.backend.persistence.domain.backend.Role@5295d3de]; Detached: [com.tdk.backend.persistence.domain.backend.Role@2b3d9d32]

在角色实体中,我没有声明字段用户,因为我不会根据角色获取所有用户

【问题讨论】:

java.lang.IllegalStateException: Multiple representations of the same entity with @ManyToMany 3 entities的可能重复 【参考方案1】:

据我说,您在 Role 实体上使用了 cascade = CascadeType.MERGE。 请删除,它会解决问题。

【讨论】:

【参考方案2】:

您正面临此问题,因为您正在将对象添加到已经可用的列表/集合中。同时使用 oneToMany 映射执行保存操作

现在从级联中删除 CascadeType.MERGE 是一种解决方案,但不是最佳解决方案,因为从级联中删除 MERGE 后,您将永远无法更新映射的对象

如果您还想执行更新操作以及保存映射对象,那么在将映射对象添加到列表/集合之前,只需在列表中检查/搜索对象,如果映射对象在列表中可用,则执行操作在那个特定的对象上。

保持级联 = CascadeType.ALL

Role role = roleService.findByName(RolesEnum.USER.getRoleName());
Note- make sure you have overridden hashcode/equals properly
boolean b = user2.getRoles().contains(role);
if (b!=true)
user2.getRoles().add(role);

 user2Service.save(user);

或使用流

Role r= user2.getRoles().stream().filter(oldRole->oldRole.equals(role)).findAny().orElse(null);
        
        if(r==null) 
 user2.getRoles().add(role);
    
     user2Service.save(user);

【讨论】:

以上是关于SpringBoot 2.0.4 中同一实体的多个表示的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Boot jpa 中将多个外键映射到同一个主键

如何在同一视图中处理同一实体类型的多个表单

为啥 Hibernate 在一对多双向更新操作中给出同一实体的多个表示?

Spring Data Rest 中同一实体的多个存储库

从同一个核心数据数据库中获取多个不同的实体

SpringBoot用实体接收Get请求传递过来的多个参数(绝对可用)