当前位置: 首页 > 知识库问答 >
问题:

当StartNode和EndNode是相同类型的对象时,Neo4j OGM RelationshipEntity

顾兴昌
2023-03-14

我在http://neo4j.com/docs/ogm/java/stable/遵循Neo4j OGM指南

对于关系实体,我们需要有一个开始节点和一个结束节点。我对这个例子做了一点修改(使它像这样更简单)-

@NodeEntity
public class Student extends Entity {
    private String name;

    @Relationship(type= "ENROLLED")
    private Enrollment enrollment = new Enrollment();

    public String getName() {
        return name;
    }

    public Enrollment getEnrollment() {
        return enrollment;
    }

    public void setEnrollment(Enrollment enrollment) {
        this.enrollment = enrollment;
    }

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }
}

@NodeEntity
public class Course extends Entity {
    private String name;

    public String getName() {
        return name;
    }

    @Relationship(type= "ENROLLED", direction= Relationship.INCOMING)
    private Enrollment enrollment = new Enrollment();

    public Enrollment getEnrollment() {
        return enrollment;
    }

    public void setEnrollment(Enrollment enrollment) {
        this.enrollment = enrollment;
    }

    public Course() {
    }

    public Course(String name) {
        this.name = name;
    }
}

@RelationshipEntity(type = "ENROLLED")
public class Enrollment extends Entity {
    @StartNode
    private Student student;

    @EndNode
    private Course course;

    private Date enrolledDate;

    public Student getStudent() {
        return student;
    }

    public Course getCourse() {
        return course;
    }

    public Date getEnrolledDate() {
        return enrolledDate;
    }

    public Enrollment() {
    }

    public Enrollment(Student student, Course course, Date enrolledDate) {
        this.student = student;
        this.course = course;
        this.enrolledDate = enrolledDate;
    }
}

现在,当我尝试保存这个在Neo4j,它工作正常。但是在我的场景中,StartNode和EndNode对象的类型是相同的-

@NodeEntity
public class MyObject extends Entity {
    private String name;

    @Relationship(type="CONNECTION")
    private MyConnection startConnection = new MyConnection();

    @Relationship(type="CONNECTION", direction= Relationship.INCOMING)
    private MyConnection endConnection = new MyConnection();

    public String getName() {
        return name;
    }

    public MyConnection getStartConnection() {
        return startConnection;
    }

    public void setStartConnection(MyConnection myConnection) {
        this.startConnection = myConnection;
    }

    public MyConnection getEndConnection() {
        return endConnection;
    }

    public void setEndConnection(MyConnection endConnection) {
        this.endConnection = endConnection;
    }

    public MyObject() {
        super();
    }

    public MyObject(String name) {
        super();
        this.name = name;
    }
}

@RelationshipEntity(type="CONNECTION")
public class MyConnection extends Entity {
    @StartNode
    private MyObject start;

    @EndNode
    private MyObject end;

    private String name;

    public String getName() {
        return name;
    }

    public MyConnection() {
        super();
    }

    public MyConnection(MyObject start, MyObject end, String name) {
        super();
        this.start = start;
        this.end = end;
        this.name = name;
    }
}

当我尝试使用-

public class Main {

    public static void main(String[] args) {
        Session session = Neo4jSessionFactory.getInstance().getNeo4jSession();

        Student s = new Student("manoj");
        Course c = new Course("physics");
        Enrollment e = new Enrollment(s, c, new Date());
        s.setEnrollment(e);
        c.setEnrollment(e);

        MyObject startObj = new MyObject("Start Object");
        MyObject endObj = new MyObject("End Object");
        MyConnection conn = new MyConnection(startObj, endObj, "Connection");
        startObj.setStartConnection(conn);
        endObj.setEndConnection(conn);

        try(Transaction tx = session.beginTransaction()) {
            session.save(s);
            session.save(c);
            session.save(e);

            session.save(startObj);
            session.save(endObj);
            session.save(conn);

            tx.commit();
        }
    }
}

学生、课程和注册对象被保存,但两个MyObject和MyConnection对象未被保存,我得到以下异常-

Exception in thread "main" java.lang.NullPointerException
    at org.neo4j.ogm.metadata.MetaData.classInfo(MetaData.java:76)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapRelationshipEntity(EntityGraphMapper.java:389)
    at org.neo4j.ogm.mapper.EntityGraphMapper.link(EntityGraphMapper.java:319)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapEntityReferences(EntityGraphMapper.java:262)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapEntity(EntityGraphMapper.java:154)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapRelatedEntity(EntityGraphMapper.java:528)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapRelationshipEntity(EntityGraphMapper.java:420)
    at org.neo4j.ogm.mapper.EntityGraphMapper.link(EntityGraphMapper.java:319)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapEntityReferences(EntityGraphMapper.java:262)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapEntity(EntityGraphMapper.java:154)
    at org.neo4j.ogm.mapper.EntityGraphMapper.map(EntityGraphMapper.java:87)
    at org.neo4j.ogm.session.delegates.SaveDelegate.save(SaveDelegate.java:65)
    at org.neo4j.ogm.session.delegates.SaveDelegate.save(SaveDelegate.java:41)
    at org.neo4j.ogm.session.Neo4jSession.save(Neo4jSession.java:370)
    at neo4j.ogm.ex.Main.main(Main.java:37)

你能帮我解决这个问题吗-1)StartNode和EndNode对象有必要是不同类型的吗?2)我的代码有问题还是Neo4j OGM的缺点?

提前感谢,

马诺伊。

尝试Luane的建议后更新-

谢谢Luanne。我尝试了你的建议,尽管我必须以不同的方式指定网址。我使用了-http://m2.neo4j.org/content/repositories/snapshots,因为默认情况下它使用https,我得到了一些安全异常,并且这种依赖关系没有被下载。

无论如何,用1.1。1-SNAPSHOT版本,我仍然得到以下错误-

Exception in thread "main" java.lang.NullPointerException
    at org.neo4j.ogm.metadata.MetaData.classInfo(MetaData.java:80)
    at org.neo4j.ogm.mapper.EntityGraphMapper.haveRelationEndsChanged(EntityGraphMapper.java:391)
    at org.neo4j.ogm.mapper.EntityGraphMapper.getRelationshipBuilder(EntityGraphMapper.java:362)
    at org.neo4j.ogm.mapper.EntityGraphMapper.link(EntityGraphMapper.java:325)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapEntityReferences(EntityGraphMapper.java:276)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapEntity(EntityGraphMapper.java:157)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapRelatedEntity(EntityGraphMapper.java:571)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapRelationshipEntity(EntityGraphMapper.java:473)
    at org.neo4j.ogm.mapper.EntityGraphMapper.link(EntityGraphMapper.java:329)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapEntityReferences(EntityGraphMapper.java:276)
    at org.neo4j.ogm.mapper.EntityGraphMapper.mapEntity(EntityGraphMapper.java:157)
    at org.neo4j.ogm.mapper.EntityGraphMapper.map(EntityGraphMapper.java:90)
    at org.neo4j.ogm.session.delegates.SaveDelegate.save(SaveDelegate.java:67)
    at org.neo4j.ogm.session.delegates.SaveDelegate.save(SaveDelegate.java:43)
    at org.neo4j.ogm.session.Neo4jSession.save(Neo4jSession.java:376)
    at neo4j.ogm.ex.Main.main(Main.java:37)

共有2个答案

夏锐藻
2023-03-14

感谢卢安的回答/建议。我偶然发现了你的优秀文章《Spring数据的精髓Neo4j 4》,并意识到我的需求与成分配对示例(在你的文章中提到)非常相似。对我来说,两个对象(MyObject)之间可能存在连接(MyConnection)。我修改过的代码如下所示-

package neo4j.ogm.ex.domain;

import java.util.HashSet;
import java.util.Set;

import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;

@NodeEntity
public class MyObject extends Entity {
    private String name;

    @Relationship(type="CONNECTION", direction= Relationship.UNDIRECTED)
    private Set<MyConnection> connections = new HashSet<>();

    public String getName() {
        return name;
    }

    public Set<MyConnection> getConnections() {
        return connections;
    }

    public void addConnection(MyConnection myConnection) {
        myConnection.getStart().getConnections().add(myConnection);
        myConnection.getEnd().getConnections().add(myConnection);
    }

    public MyObject() {
        super();
    }

    public MyObject(String name) {
        super();
        this.name = name;
    }
}

package neo4j.ogm.ex.domain;

import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;

@RelationshipEntity(type="CONNECTION")
public class MyConnection extends Entity {
    @StartNode
    private MyObject start;

    @EndNode
    private MyObject end;

    private String name;

    public String getName() {
        return name;
    }

    public MyObject getStart() {
        return start;
    }

    public MyObject getEnd() {
        return end;
    }

    public MyConnection() {
        super();
    }

    public MyConnection(MyObject start, MyObject end, String name) {
        super();
        this.start = start;
        this.end = end;
        this.name = name;
    }
}

而且它工作得很好。我还将尝试您关于删除无效初始化的其他建议。

再次感谢,

马诺伊。

司空劲
2023-03-14

您是否打算将MyObject建模为包含单个传出关系类型连接和单个传入关系类型连接,其中每个关系都有一个属性名称

因此,如果我们看EndObject,那么startConnection是与nameconn2的关系,endConnection是与nameconn1的关系?

如果是这样,我们可能会遇到问题。https://jira.spring.io/browse/DATAGRAPH-728

更新:这毕竟不是一个bug。问题在于您在MyObject中进行的初始化:

@Relationship(type="CONNECTION")
private MyConnection startConnection = new MyConnection();

@Relationship(type="CONNECTION", direction= Relationship.INCOMING)
private MyConnection endConnection = new MyConnection();

您已经初始化了一个无效的关系实体,即一个没有开始和结束节点的关系实体。

在测试中,您将startConnection设置在startObj上,但不设置末尾。实际上,endConnection由无效的关系实体表示。

删除初始化,它应该像您期望的那样工作。

 类似资料:
  • 我对sping-data-neo4j-rest有一个非常简单的问题:因为我在我的@NodeEntity中放置了@RelatedToVia关系,@StartNode和@EndNode出现在我的GET中,就像下面的JSON一样: 我的问题是:为什么会发生这种情况,因为开始节点和结束节点不是节点实体的一部分,我如何防止这种行为发生? 如果我的问题格式不好,请提前道歉,这里的第一个问题,如果有人要求,我将

  • 问题内容: 假设我有一个类A,而B,C,D是从A派生的。 如果我想知道所引用的对象的类型是什么,可以声明: 这是因为我确定从A派生的类只有B,C和D。 但是,如果我只想检查两个引用是否指向同一种对象,该怎么办? 所以像这样: 但是当然语法是错误的,如何在没有1000 if-else的情况下进行检查? 问题答案: 你的意思是 即使和属于相同的特定类,也应返回true 。 但是,如果与进行比较,则此方

  • 我有以下型号。 组织模式 用户模型 组织DTO 用户DTO 当我尝试将这些模型映射到DTO时,我得到以下错误。 处理请求时出错org.modelmapper.MappingException: ModelMapper映射错误:\r\n\r\n1)将组织映射到组织Dto时出错。 下面是我使用的转换器。 这就是映射器的配置方式。 我发现当我从UserDto类中删除组织字段并从Converter类中删除

  • 本文向大家介绍创建许多相同类型的JavaScript对象?,包括了创建许多相同类型的JavaScript对象?的使用技巧和注意事项,需要的朋友参考一下 创建单个对象比创建相同类型的多个对象要容易得多。为了克服这一障碍,javascript提供了对象构造函数。使用此函数,首先,我们必须创建对象的类型,然后,我们需要声明对象的属性 。 示例 在下面的示例中,最初,我们声明了包含“名称”,“属性”,“年

  • 问题内容: 我尝试过一些关于绑定和未绑定方法的代码。当我们调用它们时,我认为它们都会返回对象。但是,当我用于获取一些信息时,它返回的内容我并不理解。 IDE:Eclipse 插件:pydev 输出是… 为什么#1和#2返回相同的ID?他们不是不同的对象吗?如果我们分配和两个变量,#3,#4回报不同的ID。 我认为#3和#4表明它们不是同一对象,而是#1和#2 … 绑定方法的ID和未绑定方法的ID有

  • 假设我有两个列表,现在listOld包含旧员工信息,listNew包含新员工信息 我如何比较这两个列表并返回新列表,其中包含,添加的新员工列表,包含,删除的员工列表,包含上次更新已更改的员工的新列表? 我只能想到迭代列表和比较,可能最终几乎是O(n2)时间,这可以由任何util类更有效地完成吗?