You have created the application entities for movies and people, but you haven’t mapped the most unique part of the graph - relationships. In this lesson, you will map relationships between movies and people and create an application entity for relationship properties.
Add relationships to the Movie class
If you are familiar with mapping relationships in Spring applications for other types of data stores (such as relational databases), the syntax with Neo4j will not be completely foreign to you.
You will need a new field in the Movie
domain class that represents the relationship between a movie and a person. Person entities can act in
or direct
movies, so you will map the ACTED_IN
relationship from the Movie
class to the Person
class.
-
Open the
Movie.java
domain class in your project’ssrc/main/java/com/example/appspringdata
folder. -
Import
org.springframework.data.neo4j.core.schema.Relationship
andjava.util.List
classes.javaimport org.springframework.data.neo4j.core.schema.Relationship; import java.util.List;
-
Add a new field to the
Movie
class calledactors
that returns a list ofPerson
entities.javaprivate List<Person> actors;
-
Directly above the new field, annotate it with
@Relationship
and specify the relationship type asACTED_IN
and the direction asRelationship.Direction.INCOMING
.java@Relationship(value = "ACTED_IN", direction = Relationship.Direction.INCOMING) private List<Person> actors;
-
Add a getter and setter for the new field (do not add to the constructor).
javapublic List<Person> getActors() { return actors; } public void setActors(List<Person> actors) { this.actors = actors; }
The @Relationship
annotation has two attributes that are needed - relationship type (value
) and direction. In this case, you are mapping the ACTED_IN
relationship from the graph to the actors
field in the Movie
class that returns a list of Person
entities. The ACTED_IN
relationship goes from Person
to Movie
, so you specify the direction as INCOMING
in the Movie
class.
You don’t need to add the field to the constructor because you can create a movie node in the graph that doesn’t have any actors. You do need to add the field to the getters
and setters
, though, to set and retrieve actors
with their related movies.
Click to reveal the completed Movie
class code
import org.springframework.data.annotation.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Relationship;
import java.util.List;
@Node
public class Movie {
@Id
private String movieId;
private String title;
private String plot;
private String poster;
private String url;
private String imdbId;
private String tmdbId;
private String released;
private Long year;
private Long runtime;
private Long budget;
private Long revenue;
private Long imdbVotes;
private Double imdbRating;
private String[] languages;
private String[] countries;
@Relationship(value = "ACTED_IN", direction = Relationship.Direction.INCOMING)
private List<Person> actors;
public Movie(String movieId, String title, String plot, String poster, String url, String imdbId, String tmdbId,
String released, Long year, Long runtime, Long budget, Long revenue, Long imdbVotes, Double imdbRating,
String[] languages, String[] countries) {
this.movieId = movieId;
this.title = title;
this.plot = plot;
this.poster = poster;
this.url = url;
this.imdbId = imdbId;
this.tmdbId = tmdbId;
this.released = released;
this.year = year;
this.runtime = runtime;
this.budget = budget;
this.revenue = revenue;
this.imdbVotes = imdbVotes;
this.imdbRating = imdbRating;
this.languages = languages;
this.countries = countries;
}
public String getMovieId() {
return movieId;
}
public void setMovieId(String movieId) {
this.movieId = movieId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPlot() {
return plot;
}
public void setPlot(String plot) {
this.plot = plot;
}
public String getPoster() {
return poster;
}
public void setPoster(String poster) {
this.poster = poster;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getImdbId() {
return imdbId;
}
public void setImdbId(String imdbId) {
this.imdbId = imdbId;
}
public String getTmdbId() {
return tmdbId;
}
public void setTmdbId(String tmdbId) {
this.tmdbId = tmdbId;
}
public String getReleased() {
return released;
}
public void setReleased(String released) {
this.released = released;
}
public Long getYear() {
return year;
}
public void setYear(Long year) {
this.year = year;
}
public Long getRuntime() {
return runtime;
}
public void setRuntime(Long runtime) {
this.runtime = runtime;
}
public Long getBudget() {
return budget;
}
public void setBudget(Long budget) {
this.budget = budget;
}
public Long getRevenue() {
return revenue;
}
public void setRevenue(Long revenue) {
this.revenue = revenue;
}
public Long getImdbVotes() {
return imdbVotes;
}
public void setImdbVotes(Long imdbVotes) {
this.imdbVotes = imdbVotes;
}
public Double getImdbRating() {
return imdbRating;
}
public void setImdbRating(Double imdbRating) {
this.imdbRating = imdbRating;
}
public String[] getLanguages() {
return languages;
}
public void setLanguages(String[] languages) {
this.languages = languages;
}
public String[] getCountries() {
return countries;
}
public void setCountries(String[] countries) {
this.countries = countries;
}
public List<Person> getActors() {
return actors;
}
public void setActors(List<Person> actors) {
this.actors = actors;
}
}
Test the application (again!)
Start the application and execute the curl 'localhost:8080/movies/119155'
command in another terminal tab. You should see the same list of movie properties as before, plus an actors
one containing a list with fields matching the Person
class.
If you run the Cypher statement in the sandbox tab on the right, it is missing the role
property on the relationships. You will map those in the next lesson by creating a separate entity class for the relationship to include relationship properties.
Check Your Understanding
1. Movie ← Person relationships
Which direction should the ACTED_IN
relationship be mapped in the Movie
class?
-
❏ OUTGOING
-
✓ INCOMING
-
❏ BIDIRECTIONAL
Hint
A Person
entity ACTED_IN
a Movie
entity, so the relationship should be mapped coming into Movie
.
Solution
The ACTED_IN
relationship should be mapped as INCOMING
in the Movie
class.
Summary
In this lesson, you mapped the relationship between Movie
and Person
entities in the application domain by creating a property in the the Movie
class.
Next, you will map relationship properties Movie
and Person
entities with a Role
class.