简体   繁体   English

Spring没有使用ManyToMany关系

[英]Spring is not using ManyToMany relationship

I have a user and a movie model: user: 我有一个用户和一个电影模特:用户:

@Entity(name = "User")
@Table(name = "USER")
public class User {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
    @SequenceGenerator(name = "user_seq", sequenceName = "user_seq", allocationSize = 1)
    private Long id;

    @Column(name = "USERNAME", length = 50, unique = true)
    @NotNull
    @Size(min = 4, max = 50)
    private String username;

    @Column(name = "PASSWORD", length = 100)
    @NotNull
    @Size(min = 4, max = 100)
    private String password;

    @Column(name = "FIRSTNAME", length = 50)
    @NotNull
    @Size(min = 4, max = 50)
    private String firstname;

    @Column(name = "LASTNAME", length = 50)
    @NotNull
    @Size(min = 4, max = 50)
    private String lastname;

    @Column(name = "EMAIL", length = 50)
    @NotNull
    @Size(min = 4, max = 50)
    private String email;

    @Column(name = "ENABLED")
    @NotNull
    private Boolean enabled;

    @Column(name = "LASTPASSWORDRESETDATE")
    @Temporal(TemporalType.TIMESTAMP)
    @NotNull
    private Date lastPasswordResetDate;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
            name = "USER_AUTHORITY",
            joinColumns = {@JoinColumn(name = "USER_ID", referencedColumnName = "ID")},
            inverseJoinColumns = {@JoinColumn(name = "AUTHORITY_ID", referencedColumnName = "ID")})
    private List<Authority> authorities;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Boolean getEnabled() {
        return enabled;
    }

    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }

    public List<Authority> getAuthorities() {
        return authorities;
    }

    public void setAuthorities(List<Authority> authorities) {
        this.authorities = authorities;
    }

    public Date getLastPasswordResetDate() {
        return lastPasswordResetDate;
    }

    public void setLastPasswordResetDate(Date lastPasswordResetDate) {
        this.lastPasswordResetDate = lastPasswordResetDate;
    }

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "user_movie",
        joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "movie_id", referencedColumnName = "id")
    )
    private Set<Movie> movies;    

    public Set<Movie> getMovies() {
        return movies;
    }

    public void setMovies(Set<Movie> movies) {
        this.movies = movies;
    }


}

movie: 电影:

@Entity(name = "Movie")
@Table(name = "movie")
public class Movie {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String name;

    public Movie(){}

    public Movie(Integer id, String name ) {
        this.id = id;
        this.name = name;
    }

    @ManyToMany(mappedBy = "movies")
    private Set<User> users;    
    public Set<User> getUsers() {
        return users;
    }

    public void addUser(User user){
        System.out.println("ADD MOVIE: " + user);
        users.add(user);
        user.getMovies().add(this);
    }

    public void setUsers(Set<User> users) {
        this.users = users;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString(){
        return "id: " + id + "name: " + name;
    }

}

I've set up a many to many relation between these models. 我在这些模型之间建立了多对多关系。 With, if I am correct, the user as the owner of the relation. 如果我是正确的话,将用户作为关系的所有者。

In my MovieController.java I have: 在我的MovieController.java中,我有:

@RequestMapping(value = "/", method = RequestMethod.POST)
public Movie createMovie(@RequestBody Movie movie){
    return movieService.createMovie(movie);
}

This calls the MovieService.java: 这将调用MovieService.java:

@Override 
public Movie createMovie(Movie movie) {
    return movieRepository.save(movie);
}

And this calls the MovieRepository.java: 这将调用MovieRepository.java:

@Repository
public interface MovieRepository extends CrudRepository<Movie, Serializable> {}

When I call the post methode from my front-end a movie record is saved in my movie table, but no record is created in the user_movie table. 当我从前端调用post methode时,电影记录会保存在我的电影表中,但是在user_movie表中不会创建任何记录。 Doesn't Hibernate do this implicit since I set up a Many to Many relation between user and movie? 因为我在用户和电影之间建立了多对多关系,所以Hibernate不会隐式执行此操作吗?

You save the movie and in order to also have the user saved the cascade has to be set in the movie. 您保存了影片,并且还为了让用户保存了影片,必须在影片中设置级联。 Otherwise you can keep the cascade in user and save him. 否则,您可以将级联保留在用户中并保存他。

You need to put the cascade to the entity on which you call save to cascade it. 您需要将级联放置到要调用的实体上,以进行级联。

Movie{
    @ManyToMany(mappedBy = "movies", cascade={CascadeType.ALL})
    private Set<User> users;    
    public Set<User> getUsers() {
        return users;
    }
}

User {
    @ManyToMany
    @JoinTable(name = "user_movie",
        joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "movie_id", referencedColumnName = "id")
    )
    private Set<Movie> movies; 
}

Don't forget to add the user to movie and vice versa before saving. 保存之前,请不要忘记将用户添加到电影中,反之亦然。

As with all bi-directional relationships it is your object model's and application's responsibility to maintain the relationship in both direction. 与所有双向关系一样,在两个方向上保持关系都是对象模型和应用程序的责任。 There is no magic in JPA, if you add or remove to one side of the collection, you must also add or remove from the other side, see object corruption. JPA中没有魔术,如果在集合的一侧添加或删除,则还必须在另一侧添加或删除,请参见对象损坏。 Technically the database will be updated correctly if you only add/remove from the owning side of the relationship, but then your object model will be out of synch, which can cause issues. 从技术上讲,如果仅从关系的拥有方进行添加/删除,则数据库将正确更新,但是对象模型将不同步,这可能会引起问题。

see here: https://en.wikibooks.org/wiki/Java_Persistence/ManyToMany 参见此处: https : //en.wikibooks.org/wiki/Java_Persistence/ManyToMany

For the first view, your code is correct. 对于第一个视图,您的代码是正确的。
The problem can be in GenerationType.SEQUENCE (try to use GenerationType.AUTO for User's id), or you need to add @Transactional to your controller. 问题可能出在GenerationType.SEQUENCE中 (尝试使用GenerationType.AUTO作为用户的ID),或者您需要在控制器中添加@Transactional

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM