Issue Details (XML | Word | Printable)

Key: NUCCORE-676
Type: Bug Bug
Status: Closed Closed
Resolution: Cannot Reproduce
Priority: No Testcase No Testcase
Assignee: Unassigned
Reporter: fitas amine
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
DataNucleus Core

can not delete a dependant Objects

Created: 11/Mar/11 10:37 AM   Updated: 01/Apr/11 03:24 PM   Resolved: 12/Mar/11 03:08 PM
Component/s: None
Affects Version/s: None
Fix Version/s: 3.0.0.m3

File Attachments: 1. Zip Archive JDODependantObjects.zip (3 kB)
2. Zip Archive JDODependantObjects.zip (11 kB)


Datastore: MySQL
Severity: Production


 Description  « Hide
When having the following scenario, deleting an instance of A fails with a foreign-key-constraint-violation:

public class A {
  @PrimaryKey
  private String organisationID;
  @PrimaryKey
  private long aID;

  @Persistent(nullValue=NullValue.EXCEPTION, dependent="true")
  private B b;
}

public class B {
  @PrimaryKey
  private String organisationID;
  @PrimaryKey
  private long aID; // using same ID as A because it's directly dependent
}

The problem seems to be that the dependent-attribute in class "A" for field "b" is processed too early, when the A instance is still in the database and referencing the B instance.


the following exceptions happens

vax.jdo.JDODataStoreException: Delete of object "org.datanucleus.test.A@192a848" using statement "DELETE FROM `A` WHERE `AID`=?" failed : Cannot delete or update a parent row: a foreign key constraint fails (`datanucleus/a`, CONSTRAINT `A_FK1` FOREIGN KEY (`B_AID_OID`) REFERENCES `b` (`AID`))
at org.datanucleus.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:319)
at org.datanucleus.jdo.JDOPersistenceManager.jdoDeletePersistent(JDOPersistenceManager.java:736)
at org.datanucleus.jdo.JDOPersistenceManager.deletePersistent(JDOPersistenceManager.java:749)
at org.datanucleus.test.Main.main(Main.java:58)
NestedThrowablesStackTrace:
java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`datanucleus/a`, CONSTRAINT `A_FK1` FOREIGN KEY (`B_AID_OID`) REFERENCES `b` (`AID`))
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1693)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1108)
at org.datanucleus.store.rdbms.SQLController.processConnectionStatement(SQLController.java:579)
at org.datanucleus.store.rdbms.SQLController.getStatementForUpdate(SQLController.java:202)
at org.datanucleus.store.rdbms.request.DeleteRequest.execute(DeleteRequest.java:216)
at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.deleteTable(RDBMSPersistenceHandler.java:444)
at org.datanucleus.store.rdbms.RDBMSPersistenceHandler.deleteObject(RDBMSPersistenceHandler.java:413)
at org.datanucleus.jdo.state.JDOStateManagerImpl.internalDeletePersistent(JDOStateManagerImpl.java:4320)
at org.datanucleus.jdo.state.JDOStateManagerImpl.deletePersistent(JDOStateManagerImpl.java:4279)
at org.datanucleus.ObjectManagerImpl.deleteObjectInternal(ObjectManagerImpl.java:1633)
at org.datanucleus.ObjectManagerImpl.deleteObject(ObjectManagerImpl.java:1549)
at org.datanucleus.jdo.JDOPersistenceManager.jdoDeletePersistent(JDOPersistenceManager.java:731)
at org.datanucleus.jdo.JDOPersistenceManager.deletePersistent(JDOPersistenceManager.java:749)
at org.datanucleus.test.Main.main(Main.java:58)


public class B {
  @PrimaryKey
  private String organisationID;
  @PrimaryKey
  private long aID; // using same ID as A because it's directly dependent
}

The problem seems to be that the dependent-attribute in class "A" for field "b" is processed too early, when the A instance is still in the database and referencing the B instance.


Sort Order: Ascending order - Click to sort in descending order
fitas amine added a comment - 11/Mar/11 10:41 AM

fitas amine added a comment - 11/Mar/11 10:43 AM
a temporary workaround, I introduced the method NLJDOHelper.deleteAfterPrimaryObjectDeleted(...). It can be easily used in the above example like this:

public class A
implements DeleteCallback
{
  @PrimaryKey
  private String organisationID;
  @PrimaryKey
  private long aID;

  // TODO DataNucleus WORKAROUND: Omitted 'dependent' due to this
  // issue: https://www.jfire.org/modules/bugs/view.php?id=1330 [^]
  @Persistent(nullValue=NullValue.EXCEPTION) //, dependent="true")
  private B b;

  @Override
  public void jdoPreDelete() {
    NLJDOHelper.deleteAfterPrimaryObjectDeleted(this, b);
  }
}

Andy Jefferson added a comment - 12/Mar/11 02:24 PM
No java files means no testcase. Replace class files with java files

Andy Jefferson added a comment - 12/Mar/11 03:08 PM
I use SVN trunk and using that shows no problem. Since you don't say what version you're using then nothing to do. Here's the log

14:06:39,053 (org.datanucleus.test.Main.main()) WARN [DataNucleus.Datastore.Persist] - >> Delete of org.datanucleus.test.A@1af9e98 needs d
elete of related object at org.datanucleus.test.A.b but cannot delete it direct since FK is here
14:06:39,054 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Connection] - Connection found in the pool : [org.datanucleus.store.rdbm
s.ConnectionFactoryImpl$ManagedConnectionImpl@8d5aad, jdbc:hsqldb:mem:nucleus, UserName=SA, HSQL Database Engine Driver] for key=org.datanu
cleus.ObjectManagerImpl@831a91 in factory=ConnectionFactory:tx[org.datanucleus.store.rdbms.ConnectionFactoryImpl@19c9f16]
14:06:39,054 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Datastore.Retrieve] - Retrieving PreparedStatement for connection "jdbc:
hsqldb:mem:nucleus, UserName=SA, HSQL Database Engine Driver"
14:06:39,054 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Datastore.Native] - DELETE FROM A WHERE AID=<5792337027423620006>
14:06:39,055 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Datastore.Persist] - Execution Time = 1 ms (number of rows = 1)
14:06:39,055 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Persistence] - Deleting object from persistence : "org.datanucleus.test.B@14af9f7"
14:06:39,055 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Lifecycle] - Object "org.datanucleus.test.B@14af9f7" (id="org.datanucleus.test.B:5792337027423620006") has a lifecycle change : "HOLLOW"->"P_DELETED"
14:06:39,055 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Transaction] - Object "org.datanucleus.test.B@14af9f7" (id="5792337027423620006") enlisted in transactional cache
14:06:39,055 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Persistence] - Object "org.datanucleus.test.B@14af9f7" being deleted from table "B"
14:06:39,056 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Connection] - Connection found in the pool : [org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl@8d5aad, jdbc:hsqldb:mem:nucleus, UserName=SA, HSQL Database Engine Driver] for key=org.datanucleus.ObjectManagerImpl@831a91 in factory=ConnectionFactory:tx[org.datanucleus.store.rdbms.ConnectionFactoryImpl@19c9f16]
14:06:39,056 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Datastore.Retrieve] - Retrieving PreparedStatement for connection "jdbc:hsqldb:mem:nucleus, UserName=SA, HSQL Database Engine Driver"
14:06:39,056 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Datastore.Native] - DELETE FROM B WHERE AID=<5792337027423620006>
14:06:39,056 (org.datanucleus.test.Main.main()) DEBUG [DataNucleus.Datastore.Persist] - Execution Time = 0 ms (number of rows = 1)

so it deletes A first, then B