今天我在与SDN
和我的模特挣扎。
基本上我想要实现的是Foo
实体与Bar
实体的关系,但我还需要在每个nextBar
实体中保持Bar
关系,以便轻松检查一些nextBar
(Bar
s的属性已订购)。
我想通过使用:
来实现这一目标package neo4j.example.domain;
import org.springframework.data.neo4j.annotation.Fetch;
import org.springframework.data.neo4j.annotation.GraphId;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelatedTo;
import java.util.HashSet;
import java.util.Set;
@NodeEntity
public class Foo {
@GraphId
public Long id;
@Fetch
@RelatedTo
public Set<Bar> bars = new HashSet<>();
@Override
public String toString() {
return "Foo{" +
"id=" + id +
", bars=" + bars +
'}';
}
}
和
package neo4j.example.domain;
import org.springframework.data.neo4j.annotation.Fetch;
import org.springframework.data.neo4j.annotation.GraphId;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelatedTo;
@NodeEntity
public class Bar {
@GraphId
public Long id;
@Fetch
@RelatedTo
public Bar nextBar;
@Override
public String toString() {
return "Bar{" +
"id=" + id +
", nextBar=" + nextBar +
'}';
}
}
但我在项目单元测试中遇到了问题(其中一些没有通过)。经过一番调查后,我发现如果我一次性坚持数据:
public class AllInOneTest {
ApplicationContext context = new AnnotationConfigApplicationContext(ExampleNeo4jConfiguration.class);
GraphDatabaseService graphDatabaseService = context.getBean(GraphDatabaseService.class);
Neo4jOperations neo4jOperations = context.getBean(Neo4jOperations.class);
FooRepository fooRepository = context.getBean(FooRepository.class);
ExecutionEngine executionEngine = new ExecutionEngine(graphDatabaseService);
@Before
public void setUp(){
executionEngine.execute(CLEAN_DATABASE_QUERY);
}
@Test
public void shouldProperlyCreateRelationships(){
// given
Bar firstBar = new Bar();
Bar secondBar = new Bar();
Foo foo = new Foo();
firstBar.nextBar = secondBar;
foo.bars.addAll(Arrays.asList(firstBar, secondBar));
// when
fooRepository.save(foo);
// then
Foo retrievedFoo = fooRepository.findOne(foo.id);
System.out.println(retrievedFoo);
for(Bar bar: retrievedFoo.bars) {
if(firstBar.id.equals(bar.id)){
Assert.assertNotNull(bar.nextBar);
}
}
}
}
我得到了
Foo{id=0, bars=[Bar{id=2, nextBar=Bar{id=1, nextBar=null}}, Bar{id=1, nextBar=null}]}
来自我的System.out.println
所以一切都按照我想要的方式持续存在。
但通常我不是一次性获得所有Bar
(用户添加一个Bar
,5分钟后用户添加第二个Bar
) - 这就是问题。
package neo4j.example;
import neo4j.example.configuration.ExampleNeo4jConfiguration;
import neo4j.example.domain.Bar;
import neo4j.example.domain.Foo;
import neo4j.example.repository.FooRepository;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.neo4j.cypher.javacompat.ExecutionEngine;
import org.neo4j.graphdb.GraphDatabaseService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Arrays;
import static neo4j.example.repository.Query.CLEAN_DATABASE_QUERY;
public class OneByOneTest {
ApplicationContext context = new AnnotationConfigApplicationContext(ExampleNeo4jConfiguration.class);
GraphDatabaseService graphDatabaseService = context.getBean(GraphDatabaseService.class);
FooRepository fooRepository = context.getBean(FooRepository.class);
ExecutionEngine executionEngine = new ExecutionEngine(graphDatabaseService);
@Before
public void setUp(){
executionEngine.execute(CLEAN_DATABASE_QUERY);
}
@Test
public void shouldProperlyCreateRelationships(){
// given
Bar firstBar = new Bar();
Foo foo = new Foo();
foo.bars.add(firstBar);
fooRepository.save(foo);
// when
Bar secondBar = new Bar();
Foo firstRetrievedFoo = fooRepository.findOne(foo.id);
Bar[] bars = firstRetrievedFoo.bars.toArray(new Bar[0]);
bars[0].nextBar = secondBar;
firstRetrievedFoo.bars.add(secondBar);
System.out.println(firstRetrievedFoo);
fooRepository.save(firstRetrievedFoo);
System.out.println(firstRetrievedFoo);
// then
// then
Foo retrievedFoo = fooRepository.findOne(foo.id);
System.out.println(retrievedFoo);
for(Bar bar: retrievedFoo.bars) {
if(firstBar.id.equals(bar.id)){
Assert.assertNotNull(bar.nextBar);
}
}
}
}
空数据库上的此代码打印:
Foo{id=125130, bars=[Bar{id=125131, nextBar=Bar{id=null, nextBar=null}}, Bar{id=null, nextBar=null}]}
Foo{id=125130, bars=[Bar{id=125131, nextBar=Bar{id=125132, nextBar=null}}, Bar{id=125132, nextBar=null}]}
Foo{id=125130, bars=[Bar{id=125132, nextBar=null}, Bar{id=125131, nextBar=null}]}
测试失败。我可以看到,在保持与新nextBar
的关系之前和之后指向我想要的地方。从存储库中检索Foo
后,它将设置为null。
以下是示例项目:https://github.com/Adebski/neo4j-relatedto-problem/
我正在使用Neo4j
的简单映射和嵌入版本。高级映射目前不适合我,因为我的正常项目位于Scala
SBT
,而AFAIK此组合与SDN
高级映射不起作用。
答案 0 :(得分:0)
尝试单独发出save(firstBar)(在设置nextBar之后),看看是否有帮助?可能是级联保存并不像你想象的那样工作 - 也就是说我知道它会坚持任何超然的实体,但如果它没有更新所有属性/关系,我不会感到惊讶已存在的节点。一般来说,如果我没记错,@ RelatedTo只检索连接节点的id,除非它用@Fetch注释。因此,我不认为它可以很容易地确定您是否添加了关系,或者更改了属性。