找到对多对多关系集合的共享引用

Pet*_*sma 2 spring hibernate jpa

我有这个方法:

@Override 
public Movie createMovie(Movie movie) {

    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    JwtUser user = (JwtUser)authentication.getPrincipal();
    User current_user = userRepository.findOne(user.getId());       

    movieRepository.save(movie);

    userRepository.save(new HashSet<User>(){{
        add(new User(current_user, new HashSet<Movie>(){{
            add(movie);
        }}));
    }});

    return movieRepository.save(movie);
}
Run Code Online (Sandbox Code Playgroud)

当我运行我的应用程序并调用该函数时,我收到此错误:

找到对集合的共享引用:com.movi​​eseat.model.security.User.movi​​es

在我的用户模型中,我有:

@ManyToMany
@JoinTable(name = "user_movie",
    joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
    inverseJoinColumns = @JoinColumn(name = "movie_id", referencedColumnName = "id")
)
private Set<Movie> movies;
Run Code Online (Sandbox Code Playgroud)

在我的电影模型中,我有:

@ManyToMany(mappedBy = "movies", cascade = CascadeType.ALL)
private Set<User> users = new HashSet<>(); 

public Set<User> getUsers() {
    return users;
}
Run Code Online (Sandbox Code Playgroud)

什么产生错误?

Ana*_*mov 5

据我了解您的代码,您正在尝试Movie在数据库中创建一个并将其绑定到当前的User. 如果我错了纠正我。

首先,您可以从Hibernate User Guide 中了解到,双向 @ManyToMany 关联应该以不同的方式定义和使用。

双向@ManyToMany 关联有一个拥有方和一个映射方。为了保持双方之间的同步性,提供用于添加或删除子实体的辅助方法是一种很好的做法。

其次,你不应该CascadeType.ALL@ManyToMany关联上使用:

对于@ManyToMany 关联,REMOVE 实体状态转换对于级联没有意义,因为它会传播到链接表之外。由于另一端可能被父端的其他实体引用,因此自动删除可能以 ConstraintViolationException 结束。

例如,如果定义了@ManyToMany(cascade = CascadeType.ALL) 并且第一个人将被删除,Hibernate 将抛出异常,因为另一个人仍然与被删除的地址相关联。

所以,我们应该转移cascade到拥有方,改变级联类型,提供辅助方法,UserUser在我们的业务逻辑中只更新关联的拥有方()。让我们更改代码。

用户模型:

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "user_movie",
    joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
    inverseJoinColumns = @JoinColumn(name = "movie_id", referencedColumnName = "id")
)
private Set<Movie> movies = new HashSet<>();

public void addMovie(Movie movie) {
    movies.add(movie);
    movie.getUsers().add(this);
}

public void removeMovie(Movie movie) {
    movies.remove(movie);
    movie.getUsers().remove(this);
}
Run Code Online (Sandbox Code Playgroud)

电影型号:

@ManyToMany(mappedBy = "movies")
private Set<User> users = new HashSet<>();
Run Code Online (Sandbox Code Playgroud)

和业务逻辑:

@Override
public Movie createMovie(Movie movie) {

    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    JwtUser user = (JwtUser)authentication.getPrincipal();
    User current_user = userRepository.findOne(user.getId());

    current_user.addMovie(movie);
    userRepository.save(current_user);

    return movie;
}
Run Code Online (Sandbox Code Playgroud)