Home > Software engineering >  Why does Spring MVC controller method ignore FetchType.LAZY behaviour and act like FetchType.EAGER?
Why does Spring MVC controller method ignore FetchType.LAZY behaviour and act like FetchType.EAGER?

Time:08-18

My Film model explicitly states it should fetch its children Actors lazily.

@Entity
@Getter
@Setter
public class Film {

...

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
        name = "film_actor",
        joinColumns = @JoinColumn(name = "film_id"),
        inverseJoinColumns = @JoinColumn(name = "actor_id")
)
private List<Actor> cast = new ArrayList<>();

This actually works perfectly when using the service/repository in any other context:

@Override
public void run(String... args) throws Exception {
    List<Film> films = filmService.getAllFilms();
    System.out.println(films);
}

enter image description here

But then for some mysterious reason, ONLY when used in a Spring MVC controller method (using typical annotations like @Controller and @RequestMapping), it always comes back eagerly loaded...Why and how do I change this? If I have 1000 films I want to display at once, I don't want to load in a million actors!

@GetMapping("")
public String filmsPage(Model model){
    List<Film> allMyFilms = filmService.getAllFilms();
    model.addAttribute("films", allMyFilms);
    return "film/film-list";
}

enter image description here

Incidentally, for completeness, here are my service/repository layers:

@Service
@RequiredArgsConstructor
public class FilmServiceImpl implements FilmService {
private final FilmRepository filmRepo;

...

@Override
public List<Film> getAllFilms() {
    List<Film> films = filmRepo.findAll();
    return films;
}

Repository layer:

@Repository
public interface FilmRepository extends JpaRepository<Film, Long> {
    List<Film> findAll();
}

CodePudding user response:

How do you verify that the association is eager? Spring MVC has something enabled by default which is called "open session in view", which allows lazy loading until the request is finished. If you "check" whether data is loaded through your debugger, the debugger will invoke the toString method of PersistentBag which will initialize the lazy collection.

  • Related