SnejOK
SnejOK

Reputation: 107

FetchType.LAZY in ManyToMany doesnot work

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. enter image description here 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

Answers (1)

Simon Martinelli
Simon Martinelli

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

Related Questions