为了账号安全,请及时绑定邮箱和手机立即绑定

如何插入具有多对多关系的实体?

如何插入具有多对多关系的实体?

鸿蒙传说 2023-09-06 14:49:24
我正在使用 Spring 框架。我有两个实体,电影和演员,所以一部电影可以有很多演员,一个演员可以在很多电影中扮演。接下来我们有课程:import java.util.List;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.JoinTable;import javax.persistence.ManyToMany;@Entitypublic class Actor {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Long id;    private String name;    private String surname;    private String age;    @ManyToMany    @JoinTable(name = "movie_actor")    private List<Movie> movies;    public Actor(String name, String surname, String age) {        this.name = name;        this.surname = surname;        this.age = age;    }    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getSurname() {        return surname;    }    public void setSurname(String surname) {        this.surname = surname;    }    public String getAge() {        return age;    }    public void setAge(String age) {        this.age = age;    }    public List<Movie> getMovies() {        return movies;    }    public void setMovies(List<Movie> movies) {        this.movies = movies;    }   }我使用@ManyToMany注释来定义它们之间的关系。此时,我在 H2 中有一个具有 ID、AGE、NAME 和 SURNAME 列的 Actor 表,具有 ID、GENRE、TITLE 和 YEAR 的表 Movie,以及一个新表 MOVIE_ACTOR,因为带有 ACTORS_ID 和 MOVIES_ID 列的注释。直到这里看起来还可以。现在,如果我保存一部电影(我已经为两个实体实现了扩展 jpaRepository 的服务和存储库):@GetMapping("/create")public void create() {        Actor actor1 = new Actor("Pedro", "Perez", "40");        Actor actor2 = new Actor("Alfredo", "Mora", "25");        Actor actor3 = new Actor("Juan", "Martinez", "20");        Actor actor4 = new Actor("Mario", "Arenas", "30");    }(我知道这不是一个获取请求,只是为了检查电影是否正确保存,只需访问端点)我得到的是,在表 Movie 中,4 列已正确添加,但 ACTOR 和 MOVIE_ACTOR 均未完成所以省略了 actorList,这两个表是空的。为什么会发生这种情况以及如何解决?
查看完整描述

2 回答

?
斯蒂芬大帝

TA贡献1827条经验 获得超8个赞

也许您在服务方法中实现了类似的东西(您没有显示它),但我认为它丢失了:您没有级联任何东西(分别保存另一个类的对象)。您应该将@ManyToMany注释更改为@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}). 这会导致级联合并和持久操作(保存新对象或任何更改都会导致自动更新另一个对象)。

更新:基于@Alan Hay 的帖子实施

模型

@Entity

public class Actor {


    @Id

    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private Long id;

    private String name;

    private String surname;

    private String age;


    @ManyToMany

    @JoinTable(name = "movie_actor")

    private List<Movie> movies = new ArrayList<>();


    public void addMovie(Movie movie) {

        movies.add(movie);

        movie.getActors().add(this);

    }


    public void removeMovie(Movie movie) {

        movies.remove(movie);

        movie.getActors().remove(this);

    }


    // Constructors, getters and setters...


    // Equals and hashCode methods a la 

    // https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/

}

@Entity

public class Movie {


    @Id

    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private Long id;

    private String title;

    private String genre;

    private String year;


    @ManyToMany(mappedBy = "movies", cascade = {CascadeType.PERSIST, CascadeType.MERGE})

    private List<Actor> actors;


    public Movie(String title, String genre, String year, List<Actor> actors) {

        this.title = title;

        this.genre = genre;

        this.year = year;

        actors.forEach(a -> a.addMovie(this));

    }


    // Getters and setters...

}

创建方法

@GetMapping("/create")

public void create() {

    Actor actor1 = new Actor("Pedro", "Perez", "40");

    Actor actor2 = new Actor("Alfredo", "Mora", "25");

    Actor actor3 = new Actor("Juan", "Martinez", "20");

    Actor actor4 = new Actor("Mario", "Arenas", "30");


    List<Actor> actorList = new ArrayList<>();

    actorList.add(actor1);

    actorList.add(actor2);

    actorList.add(actor3);

    actorList.add(actor4);


    Movie movie = new Movie("Titanic", "Drama", "1984", actorList);


    movieService.create(movie);

}


查看完整回答
反对 回复 2023-09-06
?
慕容森

TA贡献1853条经验 获得超18个赞

这里有两个问题。

首先,您尚未设置关系的级联选项。

@ManyToMany(mappedBy = "movies", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Actor> actors;

其次,在双向关系的情况下,您有责任在内存模型中维护关系的双方。这里的关系由 Actor(没有 的一方)管理mappedBy,但您尚未将任何电影添加到 Actor 的电影集合中。

因此,如果您在电影构造函数中迭代演员并添加电影a.getMovies().add(this),那么双方都将被设置,并且数据应根据要求保存。

Hibernate 文档建议@ManyToMany应避免映射,因为在大多数情况下,您可能希望存储与关联相关的其他数据:例如,在您的情况下,角色名称。更灵活的选择是创建一个连接实体,例如 MovieAppearance,它具有 Movie、Actor 和其他所需的属性。


查看完整回答
反对 回复 2023-09-06
  • 2 回答
  • 0 关注
  • 66 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信