Search code examples
springspring-bootneo4jgraph-databasesspring-data-neo4j

Relationship Exists in neo4j but not in Spring @NodeEntity


I have a class in my domain called Activity that looks like the following

@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
@NodeEntity
public class Activity {

  @GraphId
  private Long id;

  private String title;

  private String description;

  @Relationship(type = "RELATED_TO", direction = Relationship.UNDIRECTED)
  private List<Activity> relatedActivities = new ArrayList<>();

  public Activity() {
  }

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getTitle() {
    return title;
  }

  public String getDescription() {
    return description;
  }

  public Collection<Activity> getRelatedActivities() {
    System.out.println("getting relatedActivities");
    System.out.println(relatedActivities);
    return relatedActivities;
  }

  public void addRelatedActivity(Activity activity) {
    this.relatedActivities.add(activity);
  }
}

I create relationships using the following repository class:

@RepositoryRestResource(collectionResourceRel = "relationships", path = "relationships")
public interface RelationshipRepository extends GraphRepository<Relationship> {

  @Query("MATCH (a1:Activity), (a2:Activity) " +
  "WHERE a1.title = {0} AND a2.title = {1}" +
  "CREATE (a1)-[:RELATED_TO]->(a2)")
  void addRelationship(String a1Title, String a2Title);
}

I have verified that this code works using the neo4j browser, which lets me see existing nodes and relationships between them. However, when I access getRelatedActivities() on an Activity object, it's always an empty array, even if that Activity has other Activity nodes related to it, clearly visible in neo4j.

How can I get the relatedActivites on an Activity to automatically populate based on its relationships correctly?


Solution

  • The problem in your code is that you define the "target" as an Activity here

    @Relationship(type = "RELATED_TO", direction = Relationship.UNDIRECTED)
    private List<Activity> relatedActivities = new ArrayList<>();
    

    but you also have a RelationshipEntity class in your code base: Relationship with the same type RELATED_TO.

    When OGM gets the result it tries to match every field but since it converts the relationship type RELATED_TO to the RelationshipEntity and not an Activity object, it does not fill the list in the Activity class.