Reputation: 107
I'm having a problem with, fetch = FetchType.LAZY
, it just doesn't work. I've already spent a lot of time solving this problem, can anyone help with this? I'll be very thankful. I have a genre and a country that are associated with movie manyTomany. No matter how hard I try to initialize the LAZY download, it doesn't work.I need the movie to have EAGER, and the genre and country to have LAZY.
I expect to get movie with its genre and country, But with SELECT * FROM movie WHERE id = 1 - I get an endless loop, although genre and country has LAZY download.
Sample code - below
Entities: Movie
@Entity
@Getter
@Setter
@ToString(of = {"id", "year", "name"})
@EqualsAndHashCode(of = {"id", "year"})
@NoArgsConstructor
@AllArgsConstructor
public class Movie {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
**********
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "movie_genre",
joinColumns = {
@JoinColumn(name = "movie_id")},
inverseJoinColumns = {
@JoinColumn(name = "genre_id")})
private Set<Genre> genres = new HashSet<>();
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "movie_country",
joinColumns = {
@JoinColumn(name = "movie_id")},
inverseJoinColumns = {
@JoinColumn(name = "country_id")})
private Set<Country> countries = new HashSet<>();
}
Genre
@Entity
@Getter
@Setter
@ToString(exclude = "movies")
@EqualsAndHashCode(exclude = "movies")
@NoArgsConstructor
@AllArgsConstructor
public class Genre {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Size(max = 20)
private String name;
@ManyToMany(mappedBy = "genres")
private Set<Movie> movies = new HashSet<>();
}
Country
@Entity
@Getter
@Setter
@ToString(exclude = "movies")
@EqualsAndHashCode(exclude = "movies")
@NoArgsConstructor
@AllArgsConstructor
public class Country {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Size(max = 20)
private String name;
@ManyToMany(mappedBy = "countries")
private Set<Movie> movies = new HashSet<>();
}
Controller
@RestController
public class TestController {
@Autowired
private MovieService movieService;
@Autowired
private CountryService countryService;
@Autowired
private GenreService genreService;
@GetMapping("movie")
public List<Movie> getMovieMovie(){
return movieService.getAll();
}
@GetMapping("movie/add")
public Movie create(){
Movie movie = new Movie();
movie.setName("test");
movie.setImg("test");
movie.setTime("test");
movie.setYear((short) 2332);
movie.setMovieLink("test");
movie.getCountries().add(countryService.getCountry(1));
movie.getGenres().add(genreService.getGenre(1));
return movieService.create(movie);
}
}
Service
@Service
public class MovieService {
@Autowired
private MovieRepository movieRepository;
public List<Movie> getAll(){
return movieRepository.findAll();
}
@Transactional
public Movie create(Movie mocie){
return movieRepository.save(mocie);
}
}
Upvotes: 0
Views: 1097
Reputation: 36143
Lazy loading works as expected, as it loads all data lazy.
What you are looking for is a way to break loop in the bi-directional mapping.
There you can use @JsonManagedReference
and @JsonBackReference
that you have to set on the relationships.
Please also read this: https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion
Upvotes: 3