Search code examples
javajpapersistenceeclipselinkone-to-many

No reference id in JSF JPA @OneToMany persistence


I have 2 JPA entities Xparent and Xchild, mapped with an annotation @OneToMany, a controller class Xcontroller and a JSF button “persist”. Clicking “persist” works fine so far, but there is no reference id set into the field Xchild.xparent_id in the Xchild records.

As far as I know there is everything correct annotated, since its producing records with the List<Xchild> loop in the controller class and the persist(xparent) call with the xparent object.

How can I set the field Xchild.parent_id correctly?

Current Xparent relation results:
"id" "text"
"1" "Parent"

Current Xchild relation results:
"id" "text" "xparent_id"
"1" "Child 1" ""
"2" "Child 2" ""
"3" "Child 3" ""
"4" "Child 4" ""

Expected Xchild relation (with id from Xparent):
"id" "text" "xparent_id"
"1" "Child 1" "1"
"2" "Child 2" "1"
"3" "Child 3" "1"
"4" "Child 4" "1"

Sourcecodes

Xparent.java

package model;

import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Column;;

/**
 * The persistent class for the xparent database table.
 * 
 */
@Entity
@Table(schema="public", name="xparent")
@NamedQuery(name="Xparent.findAll", query="SELECT i FROM Xparent i")
public class Xparent implements Serializable
{
    private static final long serialVersionUID = -4192021332968372280L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(unique=true, nullable=false)
    private Integer id;

    //bi-directional many-to-one association to Xchild
    @OneToMany(mappedBy="xparent", cascade=CascadeType.PERSIST)
    private List<Xchild> xchilds;

    @Column(length=2147483647)
    private String text;

    public Xparent() {}

    public Integer getId()
    {
        return this.id;
    }

    public void setId(Integer id)
    {
        this.id = id;
    }

    public String getText()
    {
        return text;
    }

    public void setText(String text)
    {
        this.text = text;
    }

    public List<Xchild> getXchilds()
    {
        return this.xchilds;
    }

    public void setXchilds(List<Xchild> xchilds)
    {
        this.xchilds = xchilds;
    }

    @Override
    public int hashCode() 
    {
        final int  prime   = 31;
        int        result  = 1;

        result = prime * result + ((id == null) ? 0 : id.hashCode());

        return result;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
        {
            return true;
        }

        if (obj == null)
        {
            return false;
        }

        if (!(obj instanceof Xparent))
        {
            return false;
        }

        Xparent other = (Xparent) obj;

        if (id == null)
        {
            if (other.id != null)
            {
                return false;
            }
        }
        else if (!id.equals(other.id))
        {
            return false;
        }

        return true;
    }
}

Xchild.java

package model;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

/**
 * The persistent class for the xchild database table.
 * 
 */
@Entity
@Table(schema="public", name="xchild")
@NamedQuery(name="Xchild.findAll", query="SELECT i FROM Xchild i")
public class Xchild implements Serializable
{
    private static final long serialVersionUID = 1337852548952194022L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(unique=true, nullable=false)
    private Integer id;

    @Column(length=2147483647)
    private String text;

    //bi-directional many-to-one association to Xparent
    @ManyToOne
    @JoinColumn(name="xparent_id")
    private Xparent xparent;    

    public Xchild() { }

    public Integer getId()
    {
        return this.id;
    }

    public void setId(Integer id)
    {
        this.id = id;
    }

    public String getText()
    {
        return text;
    }

    public void setText(String text)
    {
        this.text = text;
    }

    public Xparent getXparent()
    {
        return xparent;
    }

    public void setXparent(Xparent xparent)
    {
        this.xparent = xparent;
    }
}

Xcontroller.java

package controller;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.transaction.UserTransaction;
import model.Xchild;
import model.Xparent;

@Named
@RequestScoped
public class Xcontroller implements Serializable
{
    private static final long serialVersionUID = 8016446885968464239L;

    @PersistenceUnit
    private EntityManagerFactory    emf;

    @Resource
    private UserTransaction         ut;

    @Inject
    private Xparent              xparent;

    public Xparent getXparent()
    {
        return xparent;
    }

    public void setXparent(Xparent xparent)
    {
        this.xparent = xparent;
    }

    public String persist()
    {
        try
        {
            ut.begin();

            List<Xchild> xchilds = new ArrayList<Xchild>();

            for (int i = 1; i <= 4; i++)
            {
                Xchild   xchild = new Xchild();
                xchild.setText("Child " + i);                
                xchilds.add(xchild);
            }

            xparent.setText("Parent");
            xparent.setXchilds(xchilds);

            emf.createEntityManager().persist(xparent);
            ut.commit();

            System.out.println("*** Run method: " + this.getClass().getSimpleName() + ".persist() ***");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }

        return "/one2ManyPersistence.xhtml";
    }
}

Software

  • EclipseLink 2.5.2
  • Database: PostgreSQL 9.4
  • Applicationserver: GlassFish Server Open Source Edition 4.1 (build 13)
  • Editor: Eclipse Version: Luna Service Release 1a (4.4.1)
  • Java SDK / Runtime: 1.8.0_25

Thank you in advance!

P.S. The annotation @OneToMany(mappedBy="xparent") persisted no records. The annotation @OneToMany(mappedBy="xparent", cascade=CascadeType.PERSIST) persisted records, but with missing Xchild.xparent_id values.


Solution

  • You need to set the other side of the relation. Right now you are just setting a list of children to parent, and you need to set the parent to every child. Add this into the for loop

    xchild.setXparent(xparent);