I've built a project that uses spring-data and succeeded to create entities, add relationships with properties. All seems to run well except for updating relationships properties values, after they were once persisted.
To try to explore it, I merged the simple "worlds" example from SpringData documentation and enhanced it a bit. In this example, there is a a World entity that is related to other worlds. I added a property called "yearsToReach" to this relationship.
In my tests I create two worlds: Mars and Earth and set the yearsToReach to 10. Then, I call the WorldRepositoryService.updateYearsToOtherWorld and set the yearsToReach to 20. This method ends with a 'save' of the first World, but when quering for the World again, it doesn't seems to actually change the value in the database.
Maybe it's really simple, but I've just spent hours trying to figure out what am I doing wrong...
Here is my code, I removed some of the non-relevant parts. I really appreciate any response / code example.
This is my 'World' entity (Note: 'BaseWorld' class is not marked as @NodeEntity and it conatins only 'name' property).
@NodeEntity @Getter @Setter public class World extends BaseWorld { @GraphId private Long id; @RelatedToVia(type = OtherWorldRelationship.RELATIONSHIP_TYPE, direction = Direction.OUTGOING, elementClass = OtherWorldRelationship.class) private Set reachableByRocket = new HashSet(); public void addRocketRouteTo(World otherWorld, int yearsToReach) { OtherWorldRelationship otherWorldRelationship = new OtherWorldRelationship(); otherWorldRelationship.setWorld(this); otherWorldRelationship.setOtherWorld(otherWorld); otherWorldRelationship.setYearsToReach(yearsToReach); reachableByRocket.add(otherWorldRelationship); } public void updateYearsToOtherWorld(World otherWorld, int years) { Iterator otherWorlds = reachableByRocket.iterator(); while (otherWorlds.hasNext() ) { OtherWorldRelationship otherWorldRelationship = otherWorlds.next(); if (otherWorld.getName().equals(otherWorldRelationship.getOtherWorld().getName())){ otherWorldRelationship.setYearsToReach(years); break; } } }
This is the relationship class:
@RelationshipEntity @Getter @Setter public class OtherWorldRelationship { public static final String RELATIONSHIP_TYPE = "OtherWorld"; @GraphId Long id; @StartNode private World world; @EndNode private World otherWorld; private int yearsToReach; }
This is the WorldRepository interface - it only inherits from GraphRepository
public interface WorldRepository extends GraphRepository, NamedIndexRepository { }
And this is the WorldRepositoryService:
@Repository public class WorldRepositoryService implements IWorldRepositoryService { @Getter @Setter @Autowired private WorldRepository worldRepository; @Override @Transactional public Collection createSomeWorlds() { ArrayList newWorlds = new ArrayList(); World earth = createWorld("Earth"); newWorlds.add(earth); World mars = createWorld("Mars"); mars.addRocketRouteTo(earth, 10); newWorlds.add(mars); return newWorlds; } @Override @Transactional public World createWorld(String name) { return worldRepository.save(new World(name)); } @Override public World findWorldNamed(String name) { return worldRepository.findByPropertyValue("name", name); } @Override @Transactional public World updateYearsToOtherWorld(World mars, World earth, int years) { mars.updateYearsToOtherWorld(earth, years); return worldRepository.save(mars); } }
At last, these are lines from my test:
@Test public void testNeo4JRelationshipUpdateData() { Iterable worlds = worldRepositoryService.createSomeWorlds();//Mars and Earth World earth = worldRepositoryService.findWorldNamed("Earth"); World mars = worldRepositoryService.findWorldNamed("Mars"); Integer distanceInYears = mars.getYearsToOtherWorld(earth); System.out.println("Distance beteween Mars and " + distanceInYears); Assert.assertEquals(10, distanceInYears.intValue()); mars = worldRepositoryService.updateYearsToOtherWorld(mars, earth, 20); System.out.println("Distance beteween Mars and Earth: " + distanceInYears); Assert.assertEquals(20, distanceInYears.intValue()); mars = worldRepositoryService.findWorldNamed("Mars"); distanceInYears = mars.getYearsToOtherWorld(earth); System.out.println("Distance beteween Mars and Earth after update: " + distanceInYears); // !!! This line fails - it gets 10 instead of 20 !!! // Assert.assertEquals(20, distanceInYears.intValue()); }