我有这个方法:
@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);
}
当我运行我的应用程序并调用该函数时,我收到此错误:
找到对集合的共享引用:com.movieseat.model.security.User.movies
在我的用户模型中,我有:
@ManyToMany
@JoinTable(name = "user_movie",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "movie_id", referencedColumnName = "id")
)
private Set<Movie> movies;
在我的电影模型中,我有:
@ManyToMany(mappedBy = "movies", cascade = CascadeType.ALL)
private Set<User> users = new HashSet<>();
public Set<User> getUsers() {
return users;
}
产生错误的原因是什么?
答案 0 :(得分:1)
据我了解您的代码,您尝试在数据库中创建Movie
并将其绑定到当前User
。如果我错了,请纠正我。
首先,您可以从Hibernate User Guide学习,应该定义和使用双向@ManyToMany关联。
双向@ManyToMany关联有一个拥有者和一个mappedBy端。为了保持双方的同步性,最好提供辅助方法来添加或删除子实体。
其次,您不应在CascadeType.ALL
关联上使用@ManyToMany
:
对于@ManyToMany关联,REMOVE实体状态转换 被级联是没有意义的,因为它会传播超出 链接表。由于另一方可能被其他实体引用 在父方,自动删除可能最终在一个 ConstraintViolationException。
例如,如果定义了@ManyToMany(cascade = CascadeType.ALL)并且 第一个人将被删除,Hibernate会抛出异常 因为另一个人仍然与该地址相关联 被删除。
因此,我们应该将cascade
移到拥有方,更改级联类型,向User
提供帮助方法,并仅更新我们的关联的拥有方(User
)商业逻辑。让我们改变代码。
用户模型:
@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);
}
电影模特:
@ManyToMany(mappedBy = "movies")
private Set<User> users = new HashSet<>();
和业务逻辑:
@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;
}