无法更改或删除节点与 Neo4j OGM 和 Spring 引导数据之间的关系

Unable to change or delete relationship between nodes with Neo4j OGM and Spring Boot Data

我在使用 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)

这是尝试更新任务状态的服务方法:

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 节点(旧的和新的),或者,如果我尝试删除现有的关系,没有任何反应(旧的关系仍然存在)

可以在 GitHub 此处找到说明该问题的完整演示:

https://github.com/ADi3ek/neo4j-spring-boot-demo

非常欢迎任何可以帮助我解决该问题的线索或建议! :-)

如果您使用 @Transactional 注释您的命令(因为这是加载实体的地方),它将起作用。 潜在的问题是,如果您加载一个实体,它将使用一个新会话(上下文)打开一个新事务,找到关系并在上下文中缓存有关它们的信息。由于操作已完成,事务(和会话)随后将关闭。

随后的 save/update 未找到打开的事务,因此将打开一个新事务(具有新的会话/会话上下文)。执行保存时,它查看当前状态下的实体,不再查看旧关系。

两个答案:

  1. 这是一个错误 ;(

编辑: 经过几天的思考,我恢复了上面的说法。这不是真正的错误,而更像是意外行为。 SDN没有错。它使用两个会话(每个操作一个)来完成工作,并且由于没有人告诉它在一个事务中完成工作,因此加载的对象不是 'managed' 或 'attached' (如在 JPA 中)到会话上下文。

  1. 您可以通过为您的工作单元使用显式事务来解决这个问题

我将关闭 SDN 的问题,并尝试将所有信息迁移到 GitHub 上的两个问题之一,因为它是一个 OGM 问题。