Вызвано: org.hibernate.PersistentObjectException: отдельный объект передан для сохранения при создании нового субъекта - PullRequest
1 голос
/ 29 мая 2020

Имеются два объекта с сопоставлением manytomany, и я хочу сохранить Актера с ролями в БД для существующих ролей.

@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.

Заранее спасибо

1 Ответ

0 голосов
/ 30 мая 2020

Вам необходимо синхронизировать обе стороны отношения. В настоящее время вы используете EAGER для Actor.roles, но когда вы получаете Role, используя findByRoleName, предоставленный список не содержит список Actors (и вы не обновляете его, я имею в виду, Role.actors)

Итак, в основном у вас есть 2 варианта:

  • Используйте EAGER с обеих сторон. У него есть несколько проблем с производительностью.
  • Убедитесь, что вы получите необходимые сущности с запросами в обоих случаях (используя JOIN FETCH).

С другой стороны, это доступно для использования Set для такого рода отношений. Следующие ссылки предоставят вам дополнительную информацию:

Ссылка 1

Ссылка 2

...