hibernateforeign-keyshibernate-cascade

How to setup Hibernate cascade correctly


I have following setup

A -> B -> C

A-Mapping:

 <hibernate-mapping>
  <class name="db.base.A" table="A">
      <id name="id" type="java.lang.Integer">
          <column name="id" />        
          <generator class="identity" />    
      </id>
      <set name="Bs" table="BI18n" inverse="true" lazy="true" fetch="select" cascade="all-delete-orphan">
          <key>
              <column name="A_id"  not-null="true" />
          </key>
          <one-to-many class="db.base.B" />
      </set>        
  </class>
</hibernate-mapping>

B:

<hibernate-mapping>
  <class name="db.base.B" table="B">
      <id name="id" type="java.lang.Integer">
          <column name="id" />
          <generator class="identity" />
      </id>
      <many-to-one name="A" class="db.base.A" fetch="select">
          <column name="A_id" not-null="true" />
      </many-to-one>
      <set name="B" table="B" inverse="true" lazy="true" fetch="select" cascade="all-delete-orphan">
          <key>
              <column name="id" not-null="true" />
          </key>
          <one-to-many class="db.base.BI18n" />
      </set>
  </class>
</hibernate-mapping>

SubstanceItentifiedI18n:

<hibernate-mapping>
  <class name="db.base.BI18n" table="B18n">
      <id name="id" type="java.lang.Integer">
          <column name="id" />
          <generator class="identity" />
      </id>
      <many-to-one name="B" class="db.base.B" fetch="select">
          <column name="id" not-null="true" />
      </many-to-one>          
  </class>
</hibernate-mapping>

When I insert a new A with the complete object graph via

HibernateDaoSupport.merge(AObj);

everything is created correctly.

But if I use

HibernateDaoSupport.saveOrUpdate(AObj);

I get a DataIntegrityException

Cannot add or update a child row: a foreign key constraint fails 
(`table`.`B18n`, CONSTRAINT `B18n_fk` 
FOREIGN KEY (`id`) REFERENCES `B` (`id`))

When I look in the log4j log I see that with merge

  1. it inserts B
  2. it inserts B18n

With saveOrUpdate it

  1. inserts B18n, which obviously results in the exception

is this defined (expected) behavior or is there something wrong with my setup.


Solution

  • After some fiddling a found out what the solution was.

    I was adding new elements to an existing B. But didn't set the id of the B, because merge does a SELECT of the object graph before it issues a save/update this is no problem.

    saveOrUpdate on the other hand doesn't do it. Therefore the exception.

    Case closed ;)