我构建了一个使用spring数据的项目,并成功地创建了实体,添加了与属性的关系。除了更新关系属性值之外,所有这些属性值都运行得很好,在它们被持久化之后。
为了探索它,我合并了SpringData文档中的简单“Worlds”示例,并对其进行了一点增强。在这个例子中,有一个与其他世界相关的世界实体。我在这个关系中添加了一个名为“YearstoReach”的属性。
在我的测试中,我创建了两个世界:火星和地球,并将年可达性设置为10。然后,我调用WorldRepositoryService.UpdateYearStoOtherWorld,并将yearsToReach设置为20。这个方法以第一个世界的一个'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()); }
您确定是最后一个断言失败了吗?第二个可能会失败--更新后您不会读取distanceInYears变量。
感谢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); }
就这样!!希望它能像帮助我自己一样帮助别人。
卡梅尔
对于具有任何属性(已索引或未索引)的NodeEntity,由于某些用例,我希望将数据类型从Integer更改为String 我只是更改了定义的NodeEntity类中的数据类型。新数据成功插入数据库,属性的数据类型为新设置的数据类型(即String)。但是,在此更改之前,数据库中已存在的节点的属性数据类型仍保持为旧数据类型(即整数) 有没有办法修改数据库中所有节点的数据类型?
Spring Data Neo4J 提供高级特性,将批注的实体类映射到的 Neo4j 图形数据库。它的模块化编程模型相当于知名的 Spring 模块,建立了与图形交互的基础,并且可用于先进储存库支持。Spring Data Neo4j 是 Spring Data 项目的一部分,目标是向 NoSQL 数据库提供便捷支持。
我无融资创业新项目访问Neo4j数据与REST的例子。该示例使用嵌入式数据库,而不是独立的neo4j服务器,但我希望使用Neo4J webadmin界面来可视化我的数据。如何从此配置开始启用webadmin接口? (他们让WrappingNoServerBootstrapper与spring-data-neo4j一起使用WrappingNoServerBootstrapper,但答案中遗漏了很多知
问题内容: 我正在从“ 使用REST访问Neo4j数据”示例中引导一个新项目。该示例使用嵌入式数据库而不是独立的neo4j服务器,但是我想使用Neo4J Webadmin界面来可视化我的数据。如何从此配置开始启用Webadmin界面? (他们让WrappingNeoServerBootstrapper与spring-data-neo4j一起使用WrappingNeoServerBootstrapp
问题内容: 我有一个应用程序,它使用MySQL和通过REST的Neo4j服务器版本执行一些批处理作业。 我无法弄清楚如何使它们正确地协同工作:我可以使它们两个同时工作,但不能同时工作。我发现的帖子并非特定于Neo4j的服务器版本,也许就是问题所在,因为其他一切对我来说似乎都不错。 我的配置: JpaConfig Neo4j.xml 通过这种配置,Mysql可以完美工作,但是Neo4j不会将任何属性
假设我从存储库中查找一个对象。如果在查找后立即保存此对象,则Spring数据足够聪明,不会更新数据库。如果我更改此对象中的属性,然后保存,则spring数据会进行更新。它如何知道是否需要进行更新?