Hi Abe,
- When you delete a parent object and the operation cascades to
children, the object-level operation order is delete parent, then
delete children.
In my experience, the cascade should delete the children first. This
solves 99% of the cascade delete issues.
Craig
On Sep 11, 2006, at 4:57 PM, Abe White (JIRA) wrote:
[ http://issues.apache.org/jira/browse/OPENJPA-39?page=all ]
Abe White resolved OPENJPA-39.
--
Resolution: Won't Fix
Turns out the problem is more complicated than just having a
foreign key. The issue is:
- OpenJPA's UpdateManager plugin does not reorder SQL. It issues
SQL in the same order as the corresponding object-level
operations. The SQL-reordering UpdateManager is unique to Kodo.
- When you delete a parent object and the operation cascades to
children, the object-level operation order is delete parent, then
delete children.
- Issuing the SQL in that order will violate the FK constraint.
OpenJPA is smart enough to detect this and null the children
record's FK columns before deleting the parent.
- However, the columns in this case are non-nullable, so this
strategy doesn't work.
So, given that there are no plans to donate Kodo's SQL-reordering
UpdateManager, the options are:
1. Use nullable foreign key columns, or
2. Delete the child objects before the parent at the object level.
Also if you choose option #1, make sure to get the latest OpenJPA
from SVN, as there was a critical problem with nulling the FK
columns correctly that is now fixed (9/11/2006).
Cascade delete does not work with foreign key constraints
-
Key: OPENJPA-39
URL: http://issues.apache.org/jira/browse/OPENJPA-39
Project: OpenJPA
Issue Type: Bug
Components: jpa
Environment: Microsoft SQL Server 2000
Windows XP
Java SE 1.5
OpenJPA - source downloaded Aug 28, 2006)
Show ยป
Microsoft SQL Server 2000 Windows XP Java SE 1.5 OpenJPA - source
downloaded today (Aug 14, 2006)
Reporter: Megan
Priority: Minor
Attachments: testcase.zip
Removing a parent object in OneToMany with cascade=CascadeType.ALL
raises foreign key constraints exception
JpaParent.java
@OneToMany(mappedBy=parent, cascade=CascadeType.ALL)
private SetJpaChild children = new HashSetJpaChild();
JpaChild.java
@ManyToOne(optional=false)
@JoinColumn(name=ParentId, nullable=false)
private JpaParent parent = null;
// This raises the following exception. If foreign key is
removed, it works OK (Maybe I have to let OpenJPA know about
foreign key constraints)
JpaParent parent = em.find(JpaParent.class, 1);
em.remove(parent);
2|true|0.9.0-incubating-SNAPSHOT
org.apache.openjpa.persistence.RollbackException: The transaction
has been rolled back. See the nested exceptions for details on
the errors that occurred.
at org.apache.openjpa.persistence.EntityManagerImpl.commit
(EntityManagerImpl.java:371)
at openjpa.test.BaseTestCase.destroyTestCase(BaseTestCase.java:82)
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.junit.internal.runners.BeforeAndAfterRunner.invokeMethod
(BeforeAndAfterRunner.java:74)
at org.junit.internal.runners.BeforeAndAfterRunner.runAfters
(BeforeAndAfterRunner.java:65)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected
(BeforeAndAfterRunner.java:37)
at org.junit.internal.runners.TestMethodRunner.runMethod
(TestMethodRunner.java:75)
at org.junit.internal.runners.TestMethodRunner.run
(TestMethodRunner.java:45)
at
org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod
(TestClassMethodsRunner.java:71)
at org.junit.internal.runners.TestClassMethodsRunner.run
(TestClassMethodsRunner.java:35)
at org.junit.internal.runners.TestClassRunner$1.runUnprotected
(TestClassRunner.java:42)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected
(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestClassRunner.run
(TestClassRunner.java:52)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run
(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run
(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests
(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests
(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run
(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main
(RemoteTestRunner.java:196)
Caused by: 0|true|0.9.0-incubating-SNAPSHOT