我已经构建了一个使用spring-data的项目,并成功创建了实体,添加了与属性的关系。除了更新关系属性值之后,所有内容似乎都运行良好,只有在它们被保留后才会生效。
为了尝试探索它,我合并了SpringData文档中的简单“世界”示例并对其进行了一些改进。 在此示例中,有一个与其他世界相关的World实体。 我在这段关系中添加了一个名为“yearsToReach”的属性。
在我的测试中,我创造了两个世界:火星和地球,并将yearsToReach设置为10。 然后,我调用WorldRepositoryService.updateYearsToOtherWorld并将yearsToReach设置为20.此方法以第一个World的“save”结束,但是当再次查询World时,它似乎实际上并未更改数据库中的值。
也许这很简单,但我花了好几个小时试图弄清楚我做错了什么......
这是我的代码,我删除了一些不相关的部分。 我非常感谢任何响应/代码示例。
这是我的'世界'实体(注意:'BaseWorld'类没有标记为@NodeEntity,它只包含'name'属性。)
@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; } } }
这是关系类:
@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; }
这是WorldRepository接口 - 它只继承自GraphRepository
public interface WorldRepository extends GraphRepository, NamedIndexRepository { }
这是 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); } }
最后,这些是我测试中的行:
@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()); }
答案 0 :(得分:4)
感谢jjaderberg的帮助 - 我为了别人而粘贴了解决方案:
解决方案是保存关系本身而不是保存它的实体。 这是固定代码:
我为关系定义了新的存储库接口:
public interface OtherWorldRelationshipRepository extends GraphRepository, NamedIndexRepository { }
在WorldRepositoryService.clas中,我保存了关系而不是实体:
@Override @Transactional public OtherWorldRelationship updateYearsToOtherWorld(World mars, World earth, int years) { OtherWorldRelationship yearsToOtherWorldRelation = mars.updateYearsToOtherWorld(earth, years); return otherWorldRelationshipRepository.save(yearsToOtherWorldRelation); }
就是这样! 希望它可以帮助自己帮助自己。
卡梅尔
答案 1 :(得分:0)
你确定它是最后一个失败的断言吗?似乎第二个应该失败 - 更新后你没有读取distanceInYears变量。
答案 2 :(得分:0)
你完全正确 - 我忘了重读“distanceInYears”。不幸的是,这并没有解决问题......价值仍然是10。 两个断言都失败了(如果我评论第一个,另一个我试图再次检索“火星” - 也失败了。)
正确的测试代码如下所示:
@Test public void testNeo4JRelationshipUpdateData() { worldRepositoryService.deleteAll(); 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); distanceInYears = mars.getYearsToOtherWorld(earth); /* This is the assertion that fails: */ System.out.println("Distance beteween Mars and Earth: " + distanceInYears); Assert.assertEquals(20, distanceInYears.intValue()); /* This one also fails if we comment the two previous lines: */ mars = worldRepositoryService.findWorldNamed("Mars"); distanceInYears = mars.getYearsToOtherWorld(earth); System.out.println("Distance beteween Mars and Earth after update: " + distanceInYears); Assert.assertEquals(20, distanceInYears.intValue()); }