0

I'm trying to insert Parent with children to database. In children table parent id shouldn't be null. I've found few similar questions:

hibernate cascade to save parent and child - without answer

Save child objects automatically using JPA Hibernate - this question have answer, but I get stack overflow with it's implementation

Here is my models:

parent

@Entity
@Table(name = "report_parent")
public class ReportParent implements Serializable
{
    /**
     * 
     */
    private static final long serialVersionUID = -4551570371230260713L;

    @Id @GeneratedValue
    @Column(name="report_parent_id")    
    private int reportParentId; 


    @OneToMany(targetEntity=ReportChildren.class, mappedBy = "parent", cascade=javax.persistence.CascadeType.ALL, fetch=FetchType.LAZY)
    private List<ReportChildren> childrens = new ArrayList<ReportChildren>();


    /**
     * @return the childrens
     */
    public List<ReportChildren> getChildrens()
    {
        return childrens;
    }

    /**
     * @param childrens the childrens to set
     */
    public void setChildrens(List<ReportChildren> childrens)
    {
        this.childrens = childrens;
    }

    public void addToChildrens(ReportChildren child) {
            child.setParent(this);
            this.childrens.add(child);
        }
    //Default constructor, hashcode, equals, toString
}

child:

@Entity
@Table(name = "report_children")
public class ReportChildren implements Serializable
{
    /**
     * 
     */
    private static final long serialVersionUID = -2093943145066737073L;

    @Id @GeneratedValue
    @Column(name="report_children_id")  
    private int reportChildrenId;   

    @ManyToOne(targetEntity = ReportParent.class)
    @JoinColumn(name="parent", nullable = false)
    private ReportParent parent;

    /**
     * @return the reportChildrenId
     */
    public int getReportChildrenId()
    {
        return reportChildrenId;
    }

    /**
     * @param reportChildrenId the reportChildrenId to set
     */
    public void setReportChildrenId(int reportChildrenId)
    {
        this.reportChildrenId = reportChildrenId;
    }

    /**
     * @return the parent
     */
    public ReportParent getParent()
    {
        return parent;
    }

    /**
     * @param parent the parent to set
     */
    public void setParent(ReportParent parent)
    {
        this.parent = parent;
    }

    //Default constructor, hashcode, equals, toString

}

So I get stack overflow in my unit test

@Test
public void testLoad() throws TaxReportException
{
    ReportChildren modelChildren = new ReportChildren();        
    ReportParent model = new ReportParent();
    model.addToChildrens(modelChildren);        
    Integer id = ReportFactory.getReportDataService().load(model);
}

I understand that here

public void addToChildrens(ReportChildren child) {
        child.setParent(this);
        this.childrens.add(child);
    }

might be recurtion But than I don't understand how this suppose to work Save child objects automatically using JPA Hibernate in addToChildren method

So what is wrong with my implementation that I get stack overflow or is there any other good solution? But I really don't want to write parent and child seperatly if it's possible.

Part of stackoverflow

java.lang.StackOverflowError
    at java.util.ArrayList$Itr.<init>(ArrayList.java:820)
    at java.util.ArrayList$Itr.<init>(ArrayList.java:820)
    at java.util.ArrayList.iterator(ArrayList.java:814) 
    at java.util.AbstractCollection.toString(AbstractCollection.java:450)

    at java.lang.String.valueOf(String.java:2847)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at ua.lz.tax.model.report.data.ReportParent.toString(ReportParent.java:366)
    at java.lang.String.valueOf(String.java:2847)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at ua.lz.tax.model.report.data.ReportChildren.toString(ReportChildren.java:316) 
    at java.lang.String.valueOf(String.java:2847)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at java.util.AbstractCollection.toString(AbstractCollection.java:458)

    at java.lang.String.valueOf(String.java:2847)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at ua.lz.tax.model.report.data.ReportParent.toString(ReportParent.java:366)
    at java.lang.String.valueOf(String.java:2847)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at ua.lz.tax.model.report.data.ReportChildren.toString(ReportChildren.java:316)
    at java.lang.String.valueOf(String.java:2847)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at java.util.AbstractCollection.toString(AbstractCollection.java:458)

    ..............


    at java.lang.String.valueOf(String.java:2847)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at ua.lz.tax.model.report.data.ReportParent.toString(ReportParent.java:366)
    at java.lang.String.valueOf(String.java:2847)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at ua.lz.tax.model.report.data.ReportChildren.toString(ReportChildren.java:316)
    at java.lang.String.valueOf(String.java:2847)
    at java.lang.StringBuilder.append(StringBuilder.java:128)
    at java.util.AbstractCollection.toString(AbstractCollection.java:458)
Community
  • 1
  • 1
Evgen
  • 1,278
  • 3
  • 13
  • 25
  • There is nothing in the posted code that would cause a stack overflow. Post the relevant part of the stack trace. – Alan Hay Jun 01 '16 at 09:53
  • is both id AutoIncrement? – Duncan Jun 01 '16 at 10:04
  • Yes, both reportParentId and reportChildrenId are autoincrement. Stack added – Evgen Jun 01 '16 at 10:07
  • 2
    look at toString() of ReportParent and ReportChildren and see why it is recursing ... – Neil Stockton Jun 01 '16 at 10:09
  • Yes, the problem was with toString(); Thank you. My dump mistake. – Evgen Jun 01 '16 at 10:16
  • 2
    A bit off-topic: the word "Children" is in fact plural. Singular form is "Child". So you should name it `ReportChild` and the method should be `setChildren()`, instead of `ReportChildren` and `setChildrens()` – Adrian Shum Jun 01 '16 at 10:24
  • ok, thanks for tip. – Evgen Jun 01 '16 at 10:27
  • 1
    Still off-topic :P : More thing you need to further look into for the children handling. For example, your `setChildren()` is fragile, that 1. you shouldn't reference the input list 2. You forgot to set parent for the children. Also, you haven't taken into consideration that people may get your children list and directly add/remove child into/from it. And, people may add a child that already been put under another parent. And, people may have called `child.setParent()` but forgot to actually add to parent, etc etc. It is always a challenge to keep both side in sync and provide concrete API – Adrian Shum Jun 01 '16 at 10:32
  • Thanks, i'll try to improve my code. – Evgen Jun 01 '16 at 10:37

0 Answers0