Search code examples
javahibernatehibernate-mapping

Hibernate CRUD with lists


If I have entitys:

  1. Entity1 has list with Entity2;
  2. Entity2 has list with Entity3;
  3. Entity3 has list with Entity4;

What is operations in my code I have to do when I add new Entity4 in DB?

  1. Just set parent for Entity4 and save Entity4?

or

  1. Set parent for Entity4 and save Entity4. Add Entity4 in list of Entity3 and save Entity3.

or

  1. Add Entity4 in list of Entity3 and save Entity3. And All Entitys will be update.

Solution

  • It really depends on whether the list maintained by Entity3 is set to cascade operations such as PERSIST, MERGE, and DELETE.

    If the list is configured to cascade, then all you'd need to do is:

    • Set the parent of Entity4.
    • Add Entity4 to its parent's list and merge the modified parent.

    If cascade is not configured, then you'd need to do:

    • Set the parent of Entity4.
    • Persist the newly created instance Entity4.
    • Add Entity4 to its parent's list and merge the modified parent.

    Now you may ask why must the parent entity of Entity4 have its list updated and subsequently merged in either case?

    That is to make sure that both sides of the association are updated correctly and properly point to one another. Its very likely given the scenario that the parent side of the association is already loaded into the persistence context, so adding the child to the database won't refresh and be visible to an already loaded entity unless its refreshed. The easiest solution in this case is to always modify both sides correctly.

    public class ParentEntity {
    
      // add child to the parent entity, maintains association
      public void addChild(ChildEntity child) {
        if ( child.getParent() != null ) { 
          child.getParent().removeChild( child );
        }
        child.setParent( this );
        children.add( child );
      }
    
      // remove child from parent, disassociates association
      public void removeChild(ChildEntity child) {
        if ( this.equals( child.getParent() ) ) {
          child.setParent( null );
          children.remove( child );
        }
      }
    }
    

    I usually find it helpful to expose helper methods like the above on my domain models so that my code doesn't need to be concerned with the associations required to be maintained. I also would likely make the setter for the parent entity's list private so that only Hibernate can use it if needed to force strict use of the addChild / removeChild methods.