cancel
Showing results for 
Search instead for 
Did you mean: 

Cyclic issues with SpringBoot for Neo4j Nodes and Relationship persistence

rajanpupa
Node

Hey there,
I am trying to learn Neo4j with SpringBoot and I am facing issues creating relationships.

First I thought if I update a Persistent object, it will automatically trigger a state change in the graph. It's not happening. When I try to do a save again on the entity, I am getting stackoverflow issue because one entity is connected to another which again has a relationship defined to the original entity.

I am working with Movies graph. Basically trying to develop rest endpoints to persist new movies and Person and the Relationship between them. My code is throwing stackoverflow issue when i try to save the relationships.

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MovieDto {
	// movie properties
	private Long id;
	private String title;
	private int released;
	private String tagline;
	
	// relationship -> Person 
	private List<PersonDto> actedIn;
}
@Repository
public interface MovieRepository extends Neo4jRepository<MovieEntity, Long> {
    // save
    @Query("Merge(m: Movie {title: $title, released: $released, tagline: $tagline}) "
    		+ " ON CREATE SET m.roles = [] "
    		+ " return m ")
    public MovieEntity mergeSave(
    		@Param("title") String title,
    		@Param("released") int released,
    		@Param("tagline") String tagline
    );
}
@NodeEntity(label="Person")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PersonEntity {
	@Id
	@GeneratedValue
	private Long id;
	private String name;
	private int born;

	@Relationship(type = "ACTED_IN")
	private List<MovieEntity> movies;
	
	public void addMovie(MovieEntity movie) {
		if(this.movies == null) {
			this.movies = new ArrayList<MovieEntity>();
		}
		this.movies.add(movie);
	}
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@NodeEntity(label="Movie")
public class MovieEntity {
    @Id
    @GeneratedValue
    private Long id;
    private String title;
    private int released;
    private String tagline;

    @Relationship(type = "ACTED_IN", direction = Relationship.INCOMING)
    @JsonIgnore
    private List<RoleEntity> roles;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@RelationshipEntity(type = "ACTED_IN")
public class RoleEntity {
    @Id
    @GeneratedValue
    private Long id;
    
    @StartNode
    private PersonEntity person;
    @EndNode
    private MovieEntity movie;

    public void addRoleName(String name) {
        if (this.roles == null) {
            this.roles = new ArrayList<>();
        }
        this.roles.add(name);
    }
}
public MovieEntity saveMovie(MovieDto movie) {
		// save
		MovieEntity movieEntity = movieRepository.mergeSave(
				movie.getTitle(), 
				movie.getReleased(), 
				movie.getTagline()
		);
		
		List<PersonEntity> actorsList = new ArrayList<>();
		if(movieEntity.getRoles() == null) {
			movieEntity.setRoles(new ArrayList<RoleEntity>());
		}
		List<RoleEntity> roles = movieEntity.getRoles();
		
		for(PersonDto person: movie.getActedIn()) {
			PersonEntity personEntity = personRepository.mergeSave(person.getName(), person.getBorn());
			personEntity.addMovie(movieEntity);
			
			roles.add(
					RoleEntity.builder()
					.movie(movieEntity)
					.person(personEntity) 
					.build()
					);
			actorsList.add(personEntity);
		}
		
		movieEntity.setRoles(roles);
		
                // issue in this line (cyclic)
		movieRepository.save(movieEntity);
		
		return movieEntity;
	}

Can someone please help me understand how to do this?

1 REPLY 1

gerrit_meier
Neo4j
Neo4j

Welcome to the Neo4j community.
In general your assumption is right: When you persist the MovieEntity everything attached to it should get also saved to the graph. You did not provide the exception log but I assume that the problem might be rooted in the usage of the repositories and the transaction boundaries.
If you do not use Spring's @Transactional annotation around your unit of work, every call to the repository will create a new transaction and -in the background- a new Neo4j-OGM Session with its own cache. So it is very likely that this is the reason for not seeing the right changes to the graph.
Regarding the stackoverflow I would need to see the logs.

Also if you just have started to work with Neo4j and Spring Boot (and Spring Data Neo4j), I recommend to use Spring Data Neo4j RX (https://github.com/neo4j/sdn-rx/). It will be the successor of Spring Data Neo4j in the future.

Nodes 2022
Nodes
NODES 2022, Neo4j Online Education Summit

On November 16 and 17 for 24 hours across all timezones, you’ll learn about best practices for beginners and experts alike.