filmListRoute
layout: default title: Demo: Film List Route
Lets try to add a route to retrieve a collection of films from out database.
-
Create
FilmDAO,FilmDAOJpaImpl, andFilmControllerfiles. -
Configure them the same way we did for the Address files.
-
Create a method in your DAO that selects all the films in your database and
JOIN FETCHes the collection of actors.public List<Film> findAll(){ String query = "Select f from Film f JOIN FETCH f.actors"; return em.createQuery(query, Film.class).getResultList(); } -
Create a controller method called
indexthat has the mapping of/api/films, and calls the filmDAOfindAllmethod.@RequestMapping(path="api/films", method=RequestMethod.GET) public List<Film> index(){ return filmDAO.findAll(); } -
If you hit the route your program will hang. This is because Films have a collection of Actors, which have a collection of Films... We have recursive json and need to annotate these two entities using
@JsonBackReferenceand@JsonManagedReferenceor@JsonIgnore.
In order to do this you will need to import the library of these annotations into your JPA project. Add this Gradle dependency to your build.gradle and perform a gradle refresh.
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.13.3'
-
In your Actor class add a
@JsonIgnoreto the fieldprivate List<Film> films. This will cause the Jackson library to skip the serialization of that field.We would have to manage loading all of the other lazy loaded collections in the Film class as well. For the sake of time, put an
@JsonIgnoreon the other relationships.When you are finished the Film class should have a single relationship that is not ignored, the list of actors.
-
Run the program and hit the route
http://localhost:8080/api/films. You should get an array of json Film objects each with their own array of Actor objects.
Practice Exercise¶
The reason we had to JOIN FETCH the list of actors is due to the fact that @ManyToMany relationships are lazily loaded by default.
If a lazy-loaded collection is passed to the Jackson Library we would see a failed to lazily initialize a collection of role: entities.Language.films exception thrown.
This will be true for any field that is lazily loaded by default.