jpajakarta-eeone-to-many

JPA: Entity X has a OneToMany relationship to itself. How?


I have one Entity call Comment

Comment
+ id (PK)
+ fromUserId
+ targetId
+ replyId : This is the foreign key to id

The idea is a comment can have many replies, but a reply is also a comment. To distinguish between the two, a comment will have replyId equal -1, meanwhile a reply will have a non -1 value for replyId. Ultimately, what I want is for Comment to have a List like this

List<Comment> replyList;  //So each comment will store all their replies into this List

In JPA, I accomplish OneToMany relationship between two Entity, I create a List with the help of @OneToMany and @ManyToOne annotation, but in this case I am not sure how to accomplish this. Please help

EDIT
They way I create a Comment - Reply layout is by having one dataTable inside another

<h:form id="table">
<p:dataTable value="#{bean.comments}" var="item">
    <!-- Original Comment -->
    <p:column>
        <h:outputText value="#{item.comment}" />
    </p:column>

    <!-- Reply -->
    <p:column>
        <p:dataTable value="#{item.replies}" rendered="#{item.replies.size() > 0}" var="item2">
             <!-- Print out replies in here -->
             <h:outputText value="#{item2.comment}" />
        </p:dataTable>

        <!-- Text box and commandButton so user can add new reply -->
        <h:inputTextarea value="#{...}" />
        <p:commandButton value="Post" actionListener="#{bean.addReply(item)}" />
        <!-- Assume that I got this working, that a new Comment with correct REPLYTO_ID set -->
    </p:column>
</p:dataTable>
</h:form>

Here is my problem. When I type a reply and click Post, it creates an item entry in my database correctly, and after that recall getReplies(). I was assume at this point, replies.size() == 1, however replies.size() is equals to 0. Therefore I see nothing. I have to refresh the page, to see it display correct. I kind of see the problem here, since I generated the value of the second table by #{item.replies}, therefore if item is not update to date, then replies is not update to date. Not sure if this is JSF or JPA problem


Solution

  • You can map a self referencing entity like this:

    @Entity
    public class Comment {
        @Id
        private Long id;
    
        @ManyToOne(optional=true, fetch=FetchType.LAZY)
        @JoinColumn(name="REPLYTO_ID")
        private Comment replyTo;
    
        @OneToMany(mappedBy="replyTo")
        private List<Comment> replies = new ArrayList<Comment>();
    
        //...
    
        // link management method
        public void addToComments(Comment comment) {
            this.comments.add(comment);
            comment.setParent(parent);
        }
    }
    

    Where the root Comment has no replyTo.

    PS: make sure to set the bi-directional association correctly.