我正在使用Spring Data Neo4j 4。 假设我有类型为Person的节点,并且相应的Java域对象是
@NodeEntity
public class Person {
@GraphId private Long id;
private String name;
private String lastName;
@Relationship(type = "KNOWS")
Set<Person> myTypes;
}
我正在尝试创建一个像`
这样的图表John-KNOWS-&gt; George和John-KNOWS-&gt; Ann。安 - KNOWS-&GT;挖
`。以下是我如何设置域对象并保持持久性。
Person john = new Person("John","P");
Person george = new Person("George","B");
Person Ann = new Person("Ann","M");
Person Dug = new Person("Dug","S");
Set<Person> Persons= new HashSet<Person>();
Set<Person> Persons1= new HashSet<Person>();
Persons1.add(Dug);
Ann.setMyTypes(Persons1);
Persons.add(george);
Persons.add(Ann);
john.setMyTypes(Persons);
personRepository.save(john);
personRepository.save(george);
personRepository.save(Ann);
personRepository.save(Dug);
但令我惊讶的是,只创建了没有关系的节点。我正在调试这个并在此行之后 personRepository.save(约翰) 已创建具有关系的节点,但在后续保存期间,所有关系都已删除。 下面是日志中打印的内容,并清楚地表明关系已被删除。
Request: UNWIND {rows} as row CREATE (n:`Person`) SET n=row.props RETURN row.nodeRef as ref, ID(n) as id, row.type as type with params {rows=[{nodeRef=-2115049587, type=node, props={name=George, attrib=B}}, {nodeRef=-341599918, type=node, props={name=Ann, attrib=M}}, {nodeRef=-737678933, type=node, props={name=John, attrib=P}}, {nodeRef=-1025122203, type=node, props={name=Dug, attrib=S}}]}
Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MERGE (startNode)-[rel:`KNOWS`]->(endNode) RETURN row.relRef as ref, ID(rel) as id, row.type as type with params {rows=[{relRef=-1807300324, endNodeId=2448, type=rel, startNodeId=2450}, {relRef=-272508006, endNodeId=2451, type=rel, startNodeId=2449}, {relRef=-845107952, endNodeId=2449, type=rel, startNodeId=2450}]}
Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MATCH (startNode)-[rel:`KNOWS`]->(endNode) DELETE rel with params {rows=[{endNodeId=2448, startNodeId=2450}]}
Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MATCH (startNode)-[rel:`KNOWS`]->(endNode) DELETE rel with params {rows=[{endNodeId=2449, startNodeId=2450}]}
Request: UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MATCH (startNode)-[rel:`KNOWS`]->(endNode) DELETE rel with params {rows=[{endNodeId=2451, startNodeId=2449}]}
不知道我哪里出错了,或者这是它应该如何工作
答案 0 :(得分:2)
这种情况是OGM关系不明确的原因,因为它们存在于相同类型但存在于特定方向之间。
(john)-[:KNOWS]->(george)
也暗示乔治应该有来自约翰的传入关系,但域模型并没有反映这一点。在后续保存中,正如您所注意到的那样,关系会被删除,因为映射器由于模糊性而无法确定要保留的内容。
当您在相同类型的实体之间存在这种关系时,明确关系方向就是解决方案。 在你的情况下,从一个人到另一个人的关系总是处于传出方向,所以添加这样的方向可以清楚地表明OGM不会担心相同类型的传入关系。
@Relationship(type = "KNOWS", direction = "OUTGOING")
Set<Person> myTypes;
另外,你不必拯救每个人 - 在你的例子中,拯救约翰就足够了,因为OGM可以从约翰转移到乔治和安,从而到达挖掘。
答案 1 :(得分:0)
我认为问题在于您保存Person对象的方式。 一种解决方案是首先保存人物对象。然后添加关系并重新保存您添加关系的实体,而不是添加的实体。
例如
Person john = new Person("John","P");
Person Ann = new Person("Ann","M");
Set<Person> Persons= new HashSet<Person>();
Persons.add(Ann);
john.setMyTypes(Persons);
personRepository.save(john);
以上将拯救约翰和安,并将建立一个关系&#34; KNOWS&#34;它们之间。不需要再次拯救安。
如果您尝试在上述代码
之后再次保存AnnpersonRepository.save(Ann);
关系将被删除,因为neo4j会将其视为一个没有任何关系的实体,因为当Ann对象之前创建时关系不存在