I am currently trying out Spring boot and working with a test project, I ran into a problem with @ManyToMany-Relationships.
There should be movies, that can be saved and they can have multiple genres, actors and stuff like that. The actors can take part in many movies.
Now I can save the movie to the database, but for some reason I can only read out simple data, like the title or the year it was produced. If I try to print the genres to the command line, or the actors taking part, I get the following exception:
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.demo.Movie.actors, could not initialize proxy - no Session at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:612) at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218) at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:591) at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149) at org.hibernate.collection.internal.PersistentBag.get(PersistentBag.java:561) at com.example.demo.MoviedbApplication.main(MoviedbApplication.java:75)
Here's my Code:
ConfigurableApplicationContext run = SpringApplication.run(MoviedbApplication.class, args);
GenreRepository genreRepository = run.getBean(GenreRepository.class);
ActorRepository actorRepository = run.getBean(ActorRepository.class);
AuthorRepository authorRepository = run.getBean(AuthorRepository.class);
DirectorRepository directorRepository = run.getBean(DirectorRepository.class);
MovieRepository movieRepository = run.getBean(MovieRepository.class);
Movie theGodfather = new Movie();
theGodfather.setTitle("Der Pate");
theGodfather.setYear(1972);
theGodfather.setOriginalTitle("The Godfather");
theGodfather.setLengthInMinutes(175);
theGodfather.setPlot("Der alternde Patriarch einer Verbrecherdynastie will die Herrschaft über sein geheimes Reich auf seinen widerwilligen Sohn übertragen.");
theGodfather.setAge(16);
List<Director> dirs = new ArrayList<>();
dirs.add(new Director("Francis Ford Coppola"));
List<Actor> acts = new ArrayList<>();
acts.add(new Actor("Marlon Brando"));
acts.add(new Actor("Al Pacino"));
acts.add(new Actor("James Caan"));
List<Genre> genres = new ArrayList<>();
genres.add(new Genre("Krimi"));
genres.add(new Genre("Drama"));
List<Author> authors = new ArrayList<>();
authors.add(new Author("Mario Puzo"));
authors.add(new Author("Francis Ford Coppola"));
theGodfather.setActors(acts);
theGodfather.setAuthors(authors);
theGodfather.setDirectors(dirs);
theGodfather.setGenres(genres);
movieRepository.save(theGodfather);
List<Movie> der_pate = movieRepository.findByTitle("Der Pate");
Movie movie = der_pate.get(0);
System.out.println("Test");
System.out.println(movie.getYear());
System.out.println(movie.getTitle());
System.out.println(movie.getId());
System.out.println(movie.getActors().get(0).getName());
System.out.println(movie.getAuthors().get(0).getName());
@Entity
@Table(name="movies")
public class Movie {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String title;
private String originalTitle;
private int year;
private int age;
private int lengthInMinutes;
private String plot;
private String linkToCover;
@ManyToMany
@Cascade({CascadeType.PERSIST})
@JoinTable(
name = "movie_genres",
joinColumns = @JoinColumn(name = "movie_id"),
inverseJoinColumns = @JoinColumn(name = "genre_id")
)
private List<Genre> genres = new ArrayList<>();
@ManyToMany
@Cascade({CascadeType.PERSIST})
@JoinTable(
name = "movie_actors",
joinColumns = @JoinColumn(name = "movie_id"),
inverseJoinColumns = @JoinColumn(name="actor_id")
)
private List<Actor> actors = new ArrayList<>();
@ManyToMany
@Cascade({CascadeType.PERSIST})
@JoinTable(
name = "movie_directors",
joinColumns = @JoinColumn(name = "movie_id"),
inverseJoinColumns = @JoinColumn(name = "director_id")
)
private List<Director> directors = new ArrayList<>();
@ManyToMany
@Cascade({CascadeType.PERSIST})
@JoinTable(
name = "movie_authors",
joinColumns = @JoinColumn(name = "movie_id"),
inverseJoinColumns = @JoinColumn(name = "author_id")
)
private List<Author> authors = new ArrayList<>();
@ManyToMany
@Cascade({CascadeType.PERSIST})
@JoinTable(
name = "movie_genres",
joinColumns = @JoinColumn(name = "movie_id"),
inverseJoinColumns = @JoinColumn(name = "genre_id")
)
private List<Genre> genres = new ArrayList<>();
@ManyToMany
@Cascade({CascadeType.PERSIST})
@JoinTable(
name = "movie_actors",
joinColumns = @JoinColumn(name = "movie_id"),
inverseJoinColumns = @JoinColumn(name="actor_id")
)
private List<Actor> actors = new ArrayList<>();
@ManyToMany
@Cascade({CascadeType.PERSIST})
@JoinTable(
name = "movie_directors",
joinColumns = @JoinColumn(name = "movie_id"),
inverseJoinColumns = @JoinColumn(name = "director_id")
)
private List<Director> directors = new ArrayList<>();
@ManyToMany
@Cascade({CascadeType.PERSIST})
@JoinTable(
name = "movie_authors",
joinColumns = @JoinColumn(name = "movie_id"),
inverseJoinColumns = @JoinColumn(name = "author_id")
)
private List<Author> authors = new ArrayList<>();
@Entity @Table(name="Actor") public class Actor {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
@ManyToMany
@Cascade({CascadeType.PERSIST})
@JoinColumn(name = "movie_id")
private List<Movie> movies = new ArrayList<>();
public Actor(String name) {
this.name=name;
}`
What I already tried, was saving the actors and genres to their corresponding repositories, which lead to the following exception:
detached entity passed to persist: com.example.demo.Actor; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.example.demo.Actor
I also fumbled around with eager fetching and stuff..Now I think, I have missed something quite essential here, so I am sorry, if this sounds like a beginners question..
Thank you very much in advance!