antohoho
antohoho

Reputation: 1020

Hibernate same table parent / child relation

I have Parent/Child relationship in a single-table, let's say as simple as

id | parent_id | some_data

I am trying to understand / implement best practices how to build Hibernate classes for single table relationship.

I have a feed that comes from somewhere and it has nested JSON structure, so after parse it I want to have it representation in OracleDB.

Feed looks like

{
   1:
       => 2:
              => 3
              => 4:
                      => 5
       => 6  
}

this data should end up in db as :

1 | 0 (main rec, no parent)
2 | 1
3 | 2
4 | 2
5 | 4
6 | 1 

And it could go deeper and deeper...

I would like to traverse JSON structure and build classes that at the end I save in db

session.save(parent)

parent would be instance of my hibernate mapped class, lets name it Feed.

Each time I descend a tree, it creates a new Feed, finds it's parent and add it to the list.

Feed **parent** = new Feed();

  ->   Feed child2 = new Feed();
       child2.setParent(parent)
       parent.add(child2); 

      ->   Feed child3 = new Feed();
           child3.setParent(child2)
           child2.add(child3);

           Feed child4 = new Feed();
           child4.setParent(child2)
           child2.add(child4);

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

session.save(**parent**)

My question is could I use @ManyToOne and @OneToMany approach?

I also looked at @Inheritance(strategy = InheritanceType.SINGLE_TABLE) but I do not think I could apply it to my problem since I do not know parents, they are dynamic. I could not build parent class and extend it.

So bottom line I am trying to solve two problems

  1. Easy save on a parent level

  2. How to get data from a parent to a leaf when I need it

Some Hibernate Mapped Classes example would be very appreciated.

Upvotes: 18

Views: 22599

Answers (2)

antohoho
antohoho

Reputation: 1020

Seems like all I needed to do is:

@Entity
@Table(name = "table_name")
public class TableName {

    ......

    @Transient
    private Long parentId;

    ...... 

    @ManyToOne(fetch = FetchType.LAZY, optional=true)
    @JoinColumn(name="parent_id")
    private TableName parent;
    
    @OneToMany(mappedBy="parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval=true)
    private Set<TableName> children = new HashSet<TableName>();
}

Then simply

TableName papa = new TableName();
papa.setParent(null); // parent

TableName kid1 = new TableName();
kid1.setParent(papa);
papa.getChildren().add(kid1);

TableName kid1_1 = new TableName();
kid1_1.setParent(kid1);
kid1.getChildren().add(kid1_1);

TableName kid2 = new TableName();
kid2.setParent(papa);
papa.getChildren().add(kid2);

session.save(papa)

Upvotes: 29

anirban
anirban

Reputation: 704

Why don't you create a self referencing one to many relation keeping cascade = all. So individual child objects need not be saved separately. Only saving parent is enough. For example.

Adding a one to many relationship to a self reference parent/child

Upvotes: 0

Related Questions