Search code examples
neo4jspring-data-neo4jneo4j-ogm

Spring-Data-Neo4j How to map nodes through the service class?


I have a Spring-Boot Project using Spring-Data-Neo4j and I can't figure out how to map my relationship using my service class.

The API I've built is themed after the Series Game Of Thrones. You can construct Kinggdoms, and Castles (so far) each kingdom can have many castles but each castle is allowed one Kingdom.

The Project is on GitHub, make sure to check the Dev branch to find the latest code: https://github.com/darwin757/IceAndFire

Question:

I have my kingdom Pojo, and I've added a Relationship that it has a list of Castles:

package com.example.Westeros.Kingdoms;

import java.util.ArrayList;
import java.util.List;

import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;

import com.example.Westeros.Castles.Castle;


@NodeEntity
public class Kingdom {

@GraphId private Long id;

private String name;

@Relationship(type = "Has a")
private List<Castle> castles = new ArrayList<Castle>();

public Kingdom() {}

public Kingdom(String name) {
    super();
    this.name = name;
}

//GETERS AND SETTERS FOR NAME

public List<Castle> getCastles() {
    return castles;
}

public void addCastle(Castle castle) {
    this.castles.add(castle);
}

}

And I did the same with Castle:

package com.example.Westeros.Castles;

import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;

import com.example.Westeros.Kingdoms.Kingdom;

@NodeEntity
public class Castle {

@GraphId
private Long id;

private String name;

@Relationship(type = "belongs to")
private Kingdom kingdom;

public Castle() {}

public Castle(String name) {
    super();
    this.name = name;
}

//GETTERS AND SETTERS FOR NAME

}

Now what do I have to write in the service in order to be able to add a Kingdom and it's related Castles to the database?

So far I have this wrong method:

    //FIXME I'M WRONG
public void addCastleToKingdom(String kingdomName,String castleName) {
    Castle castle = new Castle(castleName);
    castleRepository.save(castle);
    getKingdom(kingdomName).addCastle(castle);  

I want to have a method that will pass this test

    @Test 
public void addCastleToKingdomTest() {
    kingdomService.addKingdom(theNorth);
    kingdomService.addCastleToKingdom("The North", "Winterfell");
    kingdomService.addCastleToKingdom("The North", "The Dreadfort");
    kingdomService.addCastleToKingdom("The North", "White Harbor");

    Assert.assertEquals("Winterfell", kingdomService.getKingdomsCastles("The North").get(0).getName());
    Assert.assertEquals("The Dreadfort", kingdomService.getKingdomsCastles("The North").get(1).getName());
    Assert.assertEquals("White Harbor", kingdomService.getKingdomsCastles("The North").get(2).getName());

}

Solution

  • The addCastleToKingdomTest adds a castle to the kingdom but does not persist the modifications.

    This fixes the problem :

    public void addCastleToKingdom(String kingdomName,String castleName) {
        Castle castle = new Castle(castleName);
        castleRepository.save(castle);
        Kingdom kingdom = getKingdom(kingdomName);
        kingdom.addCastle(castle);      
        kingdomRepository.save(kingdom);
    }   
    

    Or even better, as the object graph is persisted transitively by SDN :

    public void addCastleToKingdom(String kingdomName,String castleName) {
        Kingdom kingdom = getKingdom(kingdomName);
        Castle castle = new Castle(castleName);
        kingdom.addCastle(castle);
        kingdomRepository.save(kingdom);
    }