Как вставить сущность со многими ко многим отношениям? - PullRequest
0 голосов
/ 26 сентября 2019

Я работаю с Spring Framework.У меня есть две сущности, Фильм и Актер, поэтому в Фильме может быть много актеров, а Актер может играть во многих Фильмах.Ниже у нас есть классы:

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

Я использовал аннотации @ManyToMany для определения отношения между ними.

На данный момент у меня в H2 есть таблица Actor, которая имеетСтолбцы ID, AGE, NAME и SURNAME, таблица Movie с идентификаторами, GENRE, TITLE и YEAR, а также новая таблица 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");

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

(я знаю, что это не такзапрос на получение, но только для проверки правильности сохранения фильма при доступе к конечной точке) Я получаю, что в таблице Movie 4 столбца добавлены правильно, но ни ACTOR, ни MOVIE_ACTOR не завершены, поэтому actorList опущен, эти двастолы пусты.Почему это происходит и как я могу это решить?

Большое спасибо за помощь!

Ответы [ 2 ]

1 голос
/ 27 сентября 2019

Здесь есть 2 вопроса.

Во-первых, вы не установили каскадные параметры для отношений.

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

Во-вторых, в случае двунаправленных отношений вы несете ответственность за поддержание обеих сторон отношенийв модели в памяти.Связи здесь управляются актером (сторона без mappedBy), но вы не добавили ни одного фильма в коллекцию фильмов в Actor.

Итак, если вы перебираете актеров в конструкторе фильмов и добавляете фильмa.getMovies().add(this) тогда будут установлены обе стороны, и данные должны быть сохранены в соответствии с запросом.

В документах Hibernate предлагается @ManyToMany отображений, которых следует избегать, поскольку в большинстве случаев вы, вероятно, захотите хранить дополнительные данные, связанные сассоциация: в вашем случае, например, имя персонажа.Тогда более гибким вариантом является создание присоединяемого объекта, например, MovieAppearance, которое имеет необходимые свойства Movie, Actor и другие свойства.

1 голос
/ 26 сентября 2019

Может быть, вы реализовали что-то подобное в своих методах обслуживания (вы не показывали это), но я бы предположил, что это отсутствует: вы ничего не делаете каскад (соответственно, сохраняете объекты другого класса).Вам следует изменить аннотацию @ManyToMany на @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}).Это приводит к каскадному объединению и сохранению (сохранение нового объекта или любых изменений приводит к автоматическому обновлению другого).

Также рассмотрите возможность добавления правильных методов добавления и удаления для ваших списков, как описано в этом article и good равно и методы hashCode .

В общем, вы можете найти очень хорошие описания проблем, связанных с Hibernate, на странице Vlad Mihalcea .

Обновление: реализация на основе сообщения @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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...