我在使用Spring Boot(v1.5.10)和Neo4j OGM(v2.1.6,Spring Data Neo4j v4.2.10)删除或更改两个节点之间的现有关系时遇到问题。我发现使用较旧的Neo4j OGM版本(如1.x.something)的人报告了一些类似问题的痕迹,但我认为,它应该早已不复存在2.1.6和最新的Spring Boot v1版本。因此,我不知道这是回归还是我没有以正确的方式使用API。
因此,我的节点实体定义如下:
@NodeEntity
public class Task {
@GraphId
private Long id;
private String key;
@Relationship(type = "HAS_STATUS")
private Status status;
public Task() {
}
public Long getId() {
return id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
}
@NodeEntity
public class Status {
@GraphId
private Long id;
private String key;
@Relationship(type = "HAS_STATUS", direction = Relationship.INCOMING)
private Set<Task> tasks;
public Status() {
tasks = new HashSet<>();
}
public Long getId() {
return id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Set<Task> getTasks() {
return tasks;
}
public void addTask(Task task) {
tasks.add(task);
}
public boolean removeTask(Task task) {
if(this.hasTask(task)) {
return this.tasks.remove(task);
}
return false;
}
public boolean hasTask(Task task) {
return this.tasks.contains(task);
}
}
这是以类似Cypher的方式表示的:
(t:Task)-[:HAS_STATUS]->(s:Status)
以下是尝试更新任务状态的Service方法:
public void updateTaskStatus(Task task, Status status) {
Status prevStatus = task.getStatus();
if(prevStatus != null) {
prevStatus.removeTask(task);
this.saveStatus(prevStatus);
}
task.setStatus(status);
if(status != null) {
status.addTask(task);
this.saveStatus(status);
}
this.saveTask(task);
}
作为更新的结果,我得到两个HAS_STATUS
关系到两个不同的Status节点(新旧节点),或者,如果我尝试删除现有关系,则没有任何反应(旧关系仍然存在)< / p>
可以在GitHub上找到说明问题的完整演示:
https://github.com/ADi3ek/neo4j-spring-boot-demo
任何可以帮助我解决该问题的线索或建议都非常受欢迎! : - )
答案 0 :(得分:2)
如果您使用@Transactional
注释命令(因为这是实体加载的地方),它将起作用。
根本问题在于,如果加载实体,它将使用新会话(上下文)打开新事务,找到关系并在上下文中缓存有关它们的信息。然后,事务(和会话)将关闭,因为操作已完成。
后续保存/更新未找到已打开的事务,因此将打开一个新事务(具有新的会话/会话上下文)。执行保存时,它会查看处于当前状态的实体,并且不再看到旧关系。
两个答案:
编辑:经过几天的思考后,我恢复了上述声明。这不是一个真正的错误,但更像是意外的行为。 SDN没有任何问题。它使用两个会话(每个操作一个)来完成工作,因为没有人告诉它在一个事务中完成工作,所加载的对象不会被“管理”或“附加”(如JPA中)到会话上下文。
我将关闭SDN的问题并尝试将所有信息迁移到GitHub上的两个问题之一,因为它是一个OGM问题。