I am trying to remove a child value from a set on a parent object. I have set the cascade attribute to all-delete-orphan, so this should cause a deletion of the child object However, it looks like the SQL being generate is attempting to update the foreign key value to NULL instead. The child table has a foreign key constraint defined on it so this operation fails.
Just out of curiosity, I tried explicitly deleting the child element (commented out) and got a NonUniqueObjectException. I guess this is because the refresh of the parent populated the collection and when the delete was issued an attempt to assert second copy of the child into the cache was made.
From everything I have read, the initial configuration this should cause a DELETE. Is there anything I am missing? I have read the manual and searched the site for an answer, but I don't see anything obviously wrong. Which doesn't mean there isn't something obvious that I am missing.
Any construtive advice would be appreciated.
Thanks,
Karl
Hibernate version:
2.1 bundled with JBoss
Mapping documents:
Generated by XDoclet 1.2.2 from JBossIDE in Eclipse.
Parent:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping
>
<class
name="edu.srs.common.DefaultCountry"
table="country"
>
<id
name="id"
column="id"
type="int"
unsaved-value="-1"
>
<generator class="native">
<!--
To add non XDoclet generator parameters, create a file named
hibernate-generator-params-DefaultCountry.xml
containing the additional parameters and place it in your merge dir.
-->
</generator>
</id>
<version
name="version"
type="int"
column="version"
access="property"
unsaved-value="negative"
/>
<property
name="shortName"
type="string"
column="shortname"
not-null="true"
/>
<property
name="description"
type="string"
column="description"
not-null="true"
/>
<set
name="stateProvinces"
lazy="true"
cascade="all-delete-orphan"
sort="edu.srs.common.sort.StateProvinceComparator"
>
<key
column="countryid"
>
</key>
<one-to-many
class="edu.srs.common.DefaultStateProvince"
/>
</set>
<!--
To add non XDoclet property mappings, create a file named
hibernate-properties-DefaultCountry.xml
containing the additional properties and place it in your merge dir.
-->
</class>
</hibernate-mapping>
Child:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping
>
<class
name="edu.srs.common.DefaultStateProvince"
table="stprov"
>
<id
name="id"
column="id"
type="int"
unsaved-value="-1"
>
<generator class="native">
<!--
To add non XDoclet generator parameters, create a file named
hibernate-generator-params-DefaultStateProvince.xml
containing the additional parameters and place it in your merge dir.
-->
</generator>
</id>
<version
name="version"
type="int"
column="version"
access="property"
unsaved-value="negative"
/>
<property
name="shortName"
type="string"
column="shortname"
not-null="true"
/>
<property
name="description"
type="string"
column="description"
not-null="true"
/>
<many-to-one
name="country"
class="edu.srs.common.DefaultCountry"
cascade="all"
outer-join="true"
column="countryid"
not-null="true"
/>
<!--
To add non XDoclet property mappings, create a file named
hibernate-properties-DefaultStateProvince.xml
containing the additional properties and place it in your merge dir.
-->
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
ssn = ssnf.openSession();
txn = ssn.beginTransaction();
Country c = stateProvince.getCountry();
ssn.refresh(c);
c.getStateProvinces().remove(stateProvince);
//ssn.delete(stateProvince);
ssn.saveOrUpdate(c);
txn.commit();
ssn.close();
Full stack trace of any exception that occurs:
java.sql.BatchUpdateException: Duplicate key or integrity constraint violation message from server: "Cannot add or update a child row: a foreign key constraint fails"
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1492)
at org.jboss.resource.adapter.jdbc.WrappedStatement.executeBatch(WrappedStatement.java:750)
at net.sf.hibernate.impl.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:54)
at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:122)
at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2417)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2369)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2236)
at net.sf.hibernate.transaction.JTATransaction.commit(JTATransaction.java:52)
at edu.srs.common.ejb.bean.CommonOpsBean.removeStateProvince(CommonOpsBean.java:397)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.java:683)
at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:186)
at org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterceptor.java:72)
at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:84)
at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:315)
at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:148)
at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:111)
at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:191)
at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
at org.jboss.ejb.StatelessSessionContainer.internalInvoke(StatelessSessionContainer.java:331)
at org.jboss.ejb.Container.invoke(Container.java:709)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jboss.mx.server.ReflectedDispatcher.dispatch(ReflectedDispatcher.java:60)
at org.jboss.mx.server.Invocation.dispatch(Invocation.java:62)
at org.jboss.mx.server.Invocation.dispatch(Invocation.java:54)
at org.jboss.mx.server.Invocation.invoke(Invocation.java:82)
at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:197)
at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:473)
at org.jboss.invocation.jrmp.server.JRMPInvoker.invoke(JRMPInvoker.java:360)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294)
at sun.rmi.transport.Transport$1.run(Transport.java:153)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701)
at java.lang.Thread.run(Thread.java:595)
Name and version of the database you are using:
MySQL 4.1.8 using InnoDB tables
The generated SQL (show_sql=true):
select defaultcou0_.id as id0_, defaultcou0_.version as version0_, defaultcou0_.shortname as shortname0_, defaultcou0_.description as descript4_0_ from country defaultcou0_ where defaultcou0_.id=?
select stateprovi0_.id as id__, stateprovi0_.countryid as countryid__, stateprovi0_.id as id0_, stateprovi0_.version as version0_, stateprovi0_.shortname as shortname0_, stateprovi0_.description as descript4_0_, stateprovi0_.countryid as countryid0_ from stprov stateprovi0_ where stateprovi0_.countryid=?
update stprov set countryid=null where countryid=?
Debug level Hibernate log excerpt:
|