EntityExistsException при использовании @EmbeddedId с двусторонней двусторонней связью - PullRequest
0 голосов
/ 09 марта 2020

javax.persistence.EntityExistsException: Другой объект с тем же значением идентификатора уже был связан с сеансом

Ответы этого исключения затоплены через Stackoverflow, но ни один из них не соответствует моей проблеме дело. У меня есть две сущности Post и User, которые имеют отношение ManyToMany, но таблица отношений имеет два дополнительных поля: voted_at и vote.
Итак, мне нужно иметь дополнительный класс сущностей PostVote который имел бы EmbeddedId. PostVote таблица - это таблица, которая будет содержать user, проголосовавшего за post

public class PostVote implements Serializable {

    @EmbeddedId
    private PostVoteId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("postId")
    @JoinColumn(name = "post_id")
    private Post post;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("userId")
    @JoinColumn(name = "user_id")
    private User user;

    @NotNull
    @CreationTimestamp
    private LocalDateTime votedAt;

    @NotNull
    private Boolean vote = true;

    public PostVote() {
    }

    PostVote(Post post, User user) {
        this.post = post;
        this.user = user;
        this.id = new PostVoteId(post.getPostId(), user.getUserId());
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PostVote that = (PostVote) o;
        return Objects.equals(post, that.post) &&
                Objects.equals(user, that.user);
    }
    @Override
    public int hashCode() {
        return Objects.hash(post, user);
    }
}

PostVoteId субъект

@Embeddable
public class PostVoteId implements Serializable {

    @Column(name = "post_id")
    private Integer postId;

    @Column(name = "user_id")
    private Integer userId;

    PostVoteId(Integer postId, Integer userId) {
        this.postId = postId;
        this.userId = userId;
    }

    public PostVoteId() {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PostVoteId that = (PostVoteId) o;
        return Objects.equals(postId, that.postId) &&
                Objects.equals(userId, that.userId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(postId, userId);
    }
}

Я следую Влад Михалча статья . Теперь, чтобы добавить голоса к post, у меня есть метод addVote в Post.

public class Post implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
    @GenericGenerator(name = "native", strategy = "native")
    @Column(name = "post_id", unique = true, nullable = false)
    private Integer postId;

    @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<PostVote> voters = new ArrayList<>();

    public void addVote(User user){
        PostVote postVote = new PostVote(this, user);
        voters.add(postVote);
        user.getVotedPosts().add(postVote); //problem here
    }
}

Метод обслуживания, который голосует за пост:

Post post = postRepository.findById(postId);
final User user = userRepository.findById(123);
post.addVote(user);

postRepository.save(post);

Приведенный выше код выдает ошибку

javax.persistence.EntityExistsException: другой объект с таким же значением идентификатора уже был связан с сеансом: [com.sample.entities.PostVote # com.sample. сущности. PostVoteId@4ba].

Но , если я удаляю user.getVotedPosts().add(postVote) (сохраняю одностороннюю двунаправленную связь), тогда он работает нормально.

Существующие решения не помогли. Максимум говорит, что нужно проверить стратегию GenerationType и реализацию equals и hashcode. Но в моем случае оба настроены нормально.

...