自我引用@OneToMany

时间:2015-06-02 19:38:30

标签: jpa spring-data datanucleus

我有以下课程

@Entity
public class Comment extends Base {

@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Comment inReplyTo;

@OneToMany(mappedBy = "inReplyTo", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Collection<Comment> replies;

public Comment() {
}

public Collection<Comment> getReplies() {
    return replies;
}

public void setReplies(Collection<Comment> comments) {
    this.replies = comments;
}

public Comment getInReplyTo() {
    return inReplyTo;
}

public void setInReplyTo(Comment inReplyTo) {
    this.inReplyTo = inReplyTo;
}

}

添加新注释并设置inReplyTo正常工作,注释将保存到DB中。但是inReplyTo注释的回复字段为空。

也在做

c.setReplies(new ArrayList<Comment>());
c.getReplies().add(x);
repo.save(c);

导致此错误

org.datanucleus.store.types.IncompatibleFieldTypeException: Incompatible type requested for field "Comment.replies" : was java.util.Collection but should be java.util.Collection

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

您应该设置关系的两个部分:

c.setReplies(new ArrayList<Comment>());
c.getReplies().add(x);
c.setInReplyTo(x);//this is the most imporant
repo.save(c);

如果这不起作用,可能是Datanucleus中的一个错误:尝试报告并在此处的某处添加链接。

答案 1 :(得分:2)

如果我正确理解您的问题,您的代码与此类似:

Comment parent = //...

Comment reply = new Comment();
reply.setInReplyTo(parent);
reply = commentRepository.save(reply);

Collection<Comment> parentReplies = parent.getReplies();

您想知道为什么parentRepliesnull

这是预期的,因为JPA 2.0规范的§2.9实体关系说:

  

请注意,应用程序负责维护运行时关系的一致性 - 例如,确保双向关系的“一”和“多”方彼此一致时应用程序在运行时更新关系。

DataNucleus不负责实例化包含新reply评论的新集合,并将parent的回复属性设置为此集合。我检查了DataNucleus 4.1.0和Hibernate 4.3.10并验证了没有人会更新回复评论的回复属性。

您的应用程序需要确保运行时关系一致。例如,您可以向Comment类添加addReply()方法:

    public void addReply(Comment reply) {
        if (this == reply) throw new IllegalArgumentException("`reply' cannot be `this' Comment object because a comment cannot be a reply to itself.");
        if (replies == null) replies = new ArrayList<>();
        replies.add(reply);
        reply.setInReplyTo(this);
    }

然后添加回复的代码如下:

Comment parent = //...

Comment reply = new Comment();
parent.addReply(reply);
reply = commentRepository.save(reply);

Collection<Comment> parentReplies = parent.getReplies();

另外,我没有复制错误:

org.datanucleus.store.types.IncompatibleFieldTypeException: Incompatible type requested for field "Comment.replies" : was java.util.Collection but should be java.util.Collection

答案 2 :(得分:0)

我升级到DataNucleus 4.1.1,进行了清理并开始工作。