无法使用Neo4j OGM和Spring Boot Data更改或删除节点之间的关系

时间:2018-04-11 19:24:30

标签: java spring-boot spring-data-neo4j spring-data-neo4j-4 neo4j-ogm

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

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

1 个答案:

答案 0 :(得分:2)

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

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

两个答案:

  1. 这是一个错误;(
  2. 编辑:经过几天的思考后,我恢复了上述声明。这不是一个真正的错误,但更像是意外的行为。 SDN没有任何问题。它使用两个会话(每个操作一个)来完成工作,因为没有人告诉它在一个事务中完成工作,所加载的对象不会被“管理”或“附加”(如JPA中)到会话上下文。

    1. 您可以通过为您的工作单位使用显式交易来解决此问题
    2. 我将关闭SDN的问题并尝试将所有信息迁移到GitHub上的两个问题之一,因为它是一个OGM问题。