Marco Altran
Marco Altran

Reputation: 366

How do I map relationships between entities of the same super class using JPA?

I need to establish relationships between two entities using JPA/Hibernate: Child and Father, both extends the entity User. A father can have none to n children, and every children has to have a father. I can insert a father with no problem, but can't add a child that belongs to the father I have inserted before. Here is how I add a child:

    SelectStatement ss = new SelectStatement();
    ss.manager.clear();
    Father father =  ss.getFather(socialId);

    Child child = new Child();
    //Set some parameters
    dependente.setFather(father);

    titular.addChild(child);
    ss.manager.refresh(titular);
    ss.manager.persist(dependente);
    ss.manager.getTransaction().begin();
    try{
        ss.manager.getTransaction().commit();
        ss.close();
        return true;
    }
    catch(RollbackException e){
        ss.close();
        return false;
    }

Class User:

   @Entity
   @Inheritance ( strategy = InheritanceType.JOINED )
   public class User{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int pk_user;

    @Column
    private String name;        
}

Class Father:

@Entity
public class Father extends User{


    @OneToMany(mappedBy="father")
    @LazyCollection(LazyCollectionOption.FALSE)
    private Collection <Child> childs;

    @Column(nullable=true, unique=true)
    private String social_id;


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

Class Child:

@Entity
public class Child extends User{

    //Here is the problem!
    @ManyToOne(optional = false)
    @JoinColumn(name = "pk_user")
    private Father father;

}

PS: I have erased/changed some attributes for the sake of clarity, so don't worry about non-existent get/set methods, etc.

The following code produce the error "should use insertable = false, updatable = false". If I do use, I receive the error "Cannot add or update a child row".

I can erase the class User and copy all their attributes to Father and Child, creating a solution to this problem. But my real Father/Child/User classes are complex enough to avoid doing that.

Thank you.

Upvotes: 0

Views: 206

Answers (2)

Marco Altran
Marco Altran

Reputation: 366

I found the problem. I was using the same column name for 2 columns. Now in the Child table, for each child I have a pk_user that points to the super class, and "pk_father", that points to the father of the child.

@Entity
public class Child extends User{

    //name has to be != then pk_user
    @ManyToOne(optional = false)
    @JoinColumn(name = "pk_father")
    private Father father;

}

Upvotes: 0

Ilya Dyoshin
Ilya Dyoshin

Reputation: 4624

I have similar code and it works fine for me (I am in JTA environment):

create Father;
em.persist(fatherInstance);
em.flush(); //(with this I become assured, that the father is present in database )
create child;
em.persist(childInstance);
em.flush();

And do you really need ability to lazy load a titular field of your Child?, If it is required, I guess better would by using @JoinColumn(nullable=false).

But for better problem understanding - It would be better to see exact code.

Upvotes: 1

Related Questions