有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我正在使用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;

@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;

    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;
    }   
}
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

@Entity
public class Movie {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String genre;
    private String year;

    @ManyToMany(mappedBy = "movies")
    private List<Actor> actors;

    public Movie(String title, String genre, String year, List<Actor> actors) {
        this.title = title;
        this.genre = genre;
        this.year = year;
        this.actors = actors;
    }

    public Long getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getGenre() {
        return genre;
    }

    public void setGenre(String genre) {
        this.genre = genre;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public List<Actor> getActors() {
        return actors;
    }

    public void setActors(List<Actor> actors) {
        this.actors = actors;
    }
}

我使用@manytomy注释来定义它们之间的关系

在这里,我在H2中有一个表演员,有ID、年龄、姓名和姓氏列,表电影有ID、流派、标题和年份,还有一个新的表电影演员,因为有演员ID和电影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");

        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);
    }

(我知道这不是一个get请求,只是为了检查一部电影是否被正确保存,只是为了访问端点)我得到的是,在表MONIVE中,4列被正确添加,但ACTOR和movie_ACTOR都没有完成,所以actorList被ommited,这两个表是空的。为什么会发生这种情况,我该如何解决

非常感谢你的帮助


共 (1) 个答案

  1. # 1 楼答案

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

    还考虑为列表添加适当的添加和移除方法,如在这个article和良好^ ^ a3}中所描述的。

    一般来说,你可以在Vlad Mihalcea页面上找到关于Hibernate相关问题的非常好的描述

    更新:基于@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);
    }