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