首页 > 解决方案 > 引起:org.hibernate.PersistentObjectException:分离的实体在创建新actor时传递给持久化

问题描述

有以下两个具有多对多映射的实体,我想将带有角色的 Actor 保存到现有角色的数据库中。

@Entity
@Data
@Table(name = "actor")
@NoArgsConstructor
public class Actor {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long actorId;
    @Column(unique = true)
    @NotNull
    private String username;
    @NotNull
    private String password;
    @Column(unique = true)
    @NotNull
    private String email;

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "actor_role", joinColumns = @JoinColumn(name = "actorId"), inverseJoinColumns = @JoinColumn(name = "roleId"))
    private Collection<Role> roles;
}
@Entity
@Table(name = "role")
@Data
@NoArgsConstructor
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long roleId;
    @Column(unique = true)
    @NotNull
    private String roleName;

    @LazyCollection(LazyCollectionOption.FALSE)
    @ManyToMany(mappedBy = "roles")
    private Collection<Actor> actors;

    public Role(String roleName) {
        super();
        this.roleName = roleName;
    }

}

当我尝试使用 JPA ActorRepository 创建新演员时

final Actor actor = new Actor();
actor.setUsername(user.getUsername());
actor.setPassword("");
actor.setEmail(user.getUsername());
List<Role> newRoles = new ArrayList<>();
for (GrantedAuthority authority : authentication.getAuthorities()) {
    Role role = roleRepo.findByRoleName(authority.getAuthority());
    newRoles.add(role);
}
actor.setRoles(newRoles);
Actor savedActor = actorRepo.save(actor);

我得到以下错误

Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: org.db.model.Role
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127)

你能帮我解决这个问题吗,我是JPA的新手。

提前致谢

标签: springhibernatespring-bootspring-data-jpa

解决方案


您需要保持关系的双方同步。当前您正在使用EAGERforActor.roles但是,当您获得RoleusingfindByRoleName时,提供的不包含列表Actors(并且您没有更新该列表,我的意思是,Role.actors

所以,基本上你有两个选择:

  • EAGER两边都用。它有几个性能问题。
  • 确保在这两种情况下都将通过查询获得所需的实体(使用JOIN FETCH)。

另一方面,Set对于这种关系,它是可取的。以下链接将为您提供更多信息:

链接 1

链接 2


推荐阅读