Bug 224 : Delete cascade on unloaded OneToMany ... gives Referential integrity constraint violation
Priority 
High
Reported Version 
 
Logged By 
Rob
Status 
Fixed
Fixed Version 
2.4.0
Assigned To 
 
Product 
Ebean - core
Duplicate Of 
 
Created 
24/02/2010
Updated 
24/02/2010
Type 
Bug
 
Attachments 
No attachments

Caused by: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: FK_TD_CHILD_PARENT_5: PUBLIC.TD_CHILD FOREIGN KEY(PARENT_ID) REFERENCES PUBLIC.TD_PARENT(PARENT_ID); SQL statement:
delete from td_parent where parent_id=? and parent_name=? and extended_name=? [23003-115]
at org.h2.message.Message.getSQLException(Message.java:105)
at org.h2.message.Message.getSQLException(Message.java:116)
at org.h2.message.Message.getSQLException(Message.java:75)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:377)
at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:394)
at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:273)
at org.h2.table.Table.fireConstraints(Table.java:761)
at org.h2.table.Table.fireAfterRow(Table.java:776)
at org.h2.command.dml.Delete.update(Delete.java:75)
at org.h2.command.CommandContainer.update(CommandContainer.java:72)
at org.h2.command.Command.executeUpdate(Command.java:208)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:139)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:128)
at com.avaje.ebean.server.lib.sql.ExtendedPreparedStatement.executeUpdate(ExtendedPreparedStatement.java:164)
at com.avaje.ebean.server.persist.dml.DeleteHandler.execute(DeleteHandler.java:78)
at com.avaje.ebean.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:104)
... 29 more

 
Rob 24 Feb 09:36
The issue

The issue occurs when the delete must cascade (children exist and need to be deleted) and the child rows have not been loaded.

The fix is to use generate a SQL statement to delete all child rows instead.

This will work for 1 level of unloaded beans.

Rob 24 Feb 09:44
Fixed in HEAD

Fixed in HEAD.

Rob 25 Feb 09:52
Nope ... another scenario

There is another scenario that results in a ClassCastException

java.lang.RuntimeException: get id on [com.avaje.tests.model.basic.xtra.EdParent] type[com.avaje.tests.model.basic.xtra.EdExtendedParent$$EntityBean$h2] threw error.
at com.avaje.ebean.server.deploy.BeanProperty.getValue(BeanProperty.java:798)
at com.avaje.ebean.server.deploy.BeanProperty.getValueWithInheritance(BeanProperty.java:782)
at com.avaje.ebean.server.deploy.id.ImportedIdSimple.getIdValue(ImportedIdSimple.java:56)
at com.avaje.ebean.server.deploy.id.ImportedIdSimple.dmlWhere(ImportedIdSimple.java:83)
at com.avaje.ebean.server.persist.dmlbind.BindableAssocOne.dmlWhere(BindableAssocOne.java:73)
at com.avaje.ebean.server.persist.dmlbind.BindableList.dmlWhere(BindableList.java:61)
at com.avaje.ebean.server.persist.dml.DeleteMeta.genDynamicWhere(DeleteMeta.java:157)
at com.avaje.ebean.server.persist.dml.DeleteMeta.getSql(DeleteMeta.java:111)
at com.avaje.ebean.server.persist.dml.DeleteHandler.bind(DeleteHandler.java:47)
at com.avaje.ebean.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:97)
at com.avaje.ebean.server.persist.dml.DmlBeanPersister.delete(DmlBeanPersister.java:66)
at com.avaje.ebean.server.persist.DefaultPersistExecute.executeDeleteBean(DefaultPersistExecute.java:141)
at com.avaje.ebean.server.core.PersistRequestBean.executeNow(PersistRequestBean.java:394)
at com.avaje.ebean.server.core.PersistRequestBean.executeOrQueue(PersistRequestBean.java:416)
at com.avaje.ebean.server.persist.DefaultPersister.delete(DefaultPersister.java:475)
at com.avaje.ebean.server.persist.DefaultPersister.delete(DefaultPersister.java:416)
at com.avaje.ebean.server.core.DefaultServer.delete(DefaultServer.java:1649)
at com.avaje.ebean.server.persist.DefaultPersister.deleteRecurse(DefaultPersister.java:176)
at com.avaje.ebean.server.persist.DefaultPersister.deleteAssocMany(DefaultPersister.java:865)
at com.avaje.ebean.server.persist.DefaultPersister.delete(DefaultPersister.java:471)
at com.avaje.ebean.server.persist.DefaultPersister.delete(DefaultPersister.java:416)
at com.avaje.ebean.server.core.DefaultServer.delete(DefaultServer.java:1649)
at com.avaje.ebean.server.core.DefaultServer.delete(DefaultServer.java:1639)
at com.avaje.ebean.Ebean.delete(Ebean.java:647)
at com.avaje.tests.model.basic.xtra.TestDeleteUnloadedChildren.testCascadeDelete3(TestDeleteUnloadedChildren.java:88)
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 junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:81)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.ClassCastException: com.avaje.tests.model.basic.xtra.EdExtendedParent$$EntityBean$h2
at com.avaje.tests.model.basic.xtra.EdParent$$EntityBean$h2._ebean_getField(EdParent.java:1)
at com.avaje.ebean.server.reflect.EnhanceBeanReflect$Getter.get(EnhanceBeanReflect.java:144)
at com.avaje.ebean.server.deploy.BeanProperty.getValue(BeanProperty.java:791)
... 43 more

Rob 25 Feb 09:54
The issue

This will only happen with dynamic subclasses (not with enhancement).

... and obviously on an inheritance hierarchy.

Rob 25 Feb 10:04
Fixed in HEAD

Fixed in HEAD (take 2).

woResponse

Upload a file