While you can use DTO-based projections similarly to interface-based projections with a subset of existing domain class properties, DTO-based projections really shine when you want to add additional properties to an entity.
What if you wanted to calculate cast size and add it to the display data as a fun fact for users to know? In this lesson, you will create a DTO projection that contains the title
, released
, poster
, and castSize
properties to find out!
MovieDTO class
First, you need to create a DTO class that contains the few properties. Open the src/main/java/com/example/appspringdata
folder and add a new class named MovieDTOProjection.java
. Then add the properties title
, released
, poster
, and castSize
.
public class MovieDTOProjection {
String title;
String released;
String poster;
Long castSize;
//getters and setters
}
Now update the MovieRepository
and MovieController
by adding a new method to each that returns a list of MovieDTOProjection
. The repository will need a custom query that returns the movie and counts the related Person
entities as a castSize
variable, and the controller should use the /dtocast
endpoint.
interface MovieRepository extends Neo4jRepository<Movie, String> {
//other methods
@Query("MATCH (m:Movie)<-[r:ACTED_IN]-(p:Person) " +
"RETURN m, COUNT(p) AS castSize LIMIT 10;")
Iterable<MovieDTOProjection> findAllDTOProjectionsWithCustomQuery();
}
@RestController
@RequestMapping("/movies")
public class MovieController {
//other methods
@GetMapping("/dtocast")
Iterable<MovieDTOProjection> findAllMovieDTOProjections() {
return movieRepo.findAllDTOProjectionsWithCustomQuery();
}
}
In the repository method above, the custom query calculates the castSize
so that it maps to the property name in your DTO class.
Now, when you test the application and call the /movies/dtocast
endpoint, you will get the four properties specified in your DTO projection, including the calculated castSize
property.
curl 'localhost:8080/movies/movielist'
[
{
"title":"Toy Story",
"released":"1995-11-22",
"poster":"https://image.tmdb.org/t/p/w440_and_h660_face/uXDfjJbdP4ijW5hWSBrPrlKpxab.jpg",
"castSize":4
},
{
"title":"Jumanji",
"released":"1995-12-15",
"poster":"https://image.tmdb.org/t/p/w440_and_h660_face/vgpXmVaVyUL7GGiDeiK1mKEKzcX.jpg",
"castSize":4
}
//more results
]
Cast size = 4
You might notice that nearly all of the cast sizes have a value of 4
. This is because the data was only imported with a maximum of four actors per movie. If you wanted to get a more accurate cast size, you would need to alter the data import to include all actors for each movie.
Further reading
More information on projections and additional capabilities can be found in the documentation for Spring Data Neo4j Projections.
Caution! DTO-based projection
DTO projection (by nature) in Spring Data should not be used to reduce the load. SDN cannot check what will happen within the projection, and it supports capabilities (e.g. SpEL expressions) that might access fields in the domain class that are not explicitly mentioned in the projection. For this reason, SDN will fetch the whole entity, so the data transferred over the wire is not smaller.
Summary
In this lesson, you learned about and created a DTO-based projection, adding a new property to the Movie
class for a calculated cast size.
Next, you will learn about some resources for continuing to learn Spring Data Neo4j.