Inserting Null in Foreign key when saving parent table using hibernate

Viewed 1287

I was trying to save a table using Hibernate. The Parent table has One To many Relationship with its Child table. The parent table POJO has a collection of its Child tables POJO.

When I am saving the Parent table the data gets inserted into its child table as well but without its foreign key as NULL.

Below is my code: Parent:

public class Parent implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Size(max = 45)
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "parentid", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
private Collection<Child> childCollection;

public Parent() {
}

public Parent(Integer id) {
    this.id = id;
}

public Integer getId() {
    return id;
}

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

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

@XmlTransient
public Collection<Child> getChildCollection() {
    return childCollection;
}

public void setChildCollection(Collection<Child> childCollection) {
    this.childCollection = childCollection;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (id != null ? id.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof Parent)) {
        return false;
    }
    Parent other = (Parent) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "beans.Parent[ id=" + id + " ]";
}
}

Child:

public class Child implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Size(max = 45)
@Column(name = "comments")
private String comments;
@JoinColumn(name = "parentid", referencedColumnName = "id", nullable = false)
@ManyToOne(fetch = FetchType.LAZY)
private Parent parentid;

public Child() {
}

public Child(Integer id) {
    this.id = id;
}

public Integer getId() {
    return id;
}

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

public String getComments() {
    return comments;
}

public void setComments(String comments) {
    this.comments = comments;
}

public Parent getParentid() {
    return parentid;
}

public void setParentid(Parent parentid) {
    this.parentid = parentid;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (id != null ? id.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof Child)) {
        return false;
    }
    Child other = (Child) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "beans.Child[ id=" + id + " ]";
} }

Hibernate Service:

public class HibernateSave {
public static void main(String[] args) {
            SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

    Session session = sessionFactory.openSession();

            Transaction tx1 = session.beginTransaction();

    Parent parent = new Parent();
            Child child1 = new Child();
            parent.setName("Name");
            child1.setComments("Hey");
            //child1.setParentid(parent);
            List<Child> childs = new ArrayList<Child>();
            childs.add(child1);


            parent.setChildCollection(childs);

            System.out.println("parent Saved id="+session.save(parent));
            tx1.commit();
    session.flush(); //address will not get saved without this
    System.out.println("*****");



} }

I found a solution where I reversed mapped my child to parent as below

child1.setParentid(parent);

But I am thinking if this could be avoided. I hope there is anyother way round where I donot need to map my every child to its parent.

Kinldy help and also if you could explain.

1 Answers

If you update one side of a bi-directional relationship you also have to update the other end of it as it's the applications responsibility to maintain the correct state of the Domain Model.

One thing you could do is create a method in Parent to add Childs:

public void addChild(Child child) {
    childCollection.add(child);
    child.setParentId(this);
}

or/and the other way round in Child:

public void setParent(Parent parent) {
    parent.getChildCollection().add(this);
    this.setParentId(parent)
}

(code without necessary null-checks etc. but should give the idea)

and thus making the code a little less error-prone (i.e. forgetting to update the other side of the relationship).

There also seems to be a Bytecode-Enhancement which will add similar code to the class files of your entities, but I have no experience with how well that works (see here for details)

Related