persistence@glassfish.java.net

Re: Cascade question

From: Markus Fuchs <Markus.Fuchs_at_Sun.COM>
Date: Fri, 10 Nov 2006 17:26:33 -0800
Hi Greg,

you have to define one side of the relationship as "owning" side. The owning side should be the side with  the foreign key. In your mapping, obviously, both sides have a foreign key, as you define a join column on both sides. Assuming ShoppingCard as "owning" side, an example mapping would be

On the other end, in my ShoppingCart class, I have:

  @OneToOne
  @JoinColumn(name="customer_nature")
  private CustomerNature customerNature;


  In my CustomerNature class, could be:

  @OneToOne(cascade={CascadeType.ALL},
mappedBy="customerNature")
  private ShoppingCart shoppingCart

Please also see the JPA spec,

2.1.8.1 Bidirectional OneToOne Relationships
9.1.23 OneToOne Annotation

If both sides don't have a foreign key, you could use

9.1.32 PrimaryKeyJoinColumn Annotation

HTH,

-- markus.

Greg Ederer wrote:
Hi,

In my CustomerNature class, I have:

  @OneToOne(cascade={CascadeType.ALL})
  @JoinColumn(name="shopping_cart")
  private ShoppingCart shoppingCart


On the other end, in my ShoppingCart class, I have:

  @OneToOne
  @JoinColumn(name="customer_nature")
  private CustomerNature customerNature;


When I remove (EntityManager.remove()) a CustomerNature that has a reference to a ShoppingCart, I get:

Internal Exception: org.postgresql.util.PSQLException: ERROR: update or delete on "customer_nature" violates foreign key constraint "fk_shopping_cart_customer_nature" on "shopping_cart"
  Detail: Key (id)=(2) is still referenced from table "shopping_cart".Error Code: 0
Call:DELETE FROM customer_nature WHERE (ID = ?)
    bind => [2]
Query:DeleteObjectQuery(com.ergonosis.model.CustomerNature[id=2])
    at oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:109)
    at oracle.toplink.essentials.internal.ejb.cmp3.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:45)
    at com.ergonosis.model.AppUserTest.shop(AppUserTest.java:235)
    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.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
    at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
    at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
    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 junit.framework.JUnit4TestAdapter.run(JUnit4TestAdapter.java:32)
    at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:297)
    at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:672)
    at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:567)
Caused by: Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2006.8 (Build 060830)): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: update or delete on "customer_nature" violates foreign key constraint "fk_shopping_cart_customer_nature" on "shopping_cart"
  Detail: Key (id)=(2) is still referenced from table "shopping_cart".Error Code: 0
Call:DELETE FROM customer_nature WHERE (ID = ?)
    bind => [2]
Query:DeleteObjectQuery(com.ergonosis.model.CustomerNature[id=2])
    at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:295)
    at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:639)
    at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:688)
    at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:477)
    at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:437)
    at oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:675)
    at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:213)
    at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:199)
    at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.deleteObject(DatasourceCallQueryMechanism.java:190)
    at oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.deleteObject(StatementQueryMechanism.java:115)
    at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeDatabaseQuery(DeleteObjectQuery.java:132)
    at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:609)
    at oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:536)
    at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:123)
    at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:95)
    at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:95)
    at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2218)
    at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:937)
    at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:894)
    at oracle.toplink.essentials.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:322)
    at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1033)
    at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:357)
    at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1112)
    at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:82)
    at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:842)
    at oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:90)
    ... 20 more
Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on "customer_nature" violates foreign key constraint "fk_shopping_cart_customer_nature" on "shopping_cart"
  Detail: Key (id)=(2) is still referenced from table "shopping_cart".
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1525)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1309)


What I would like is for the delete of the customer_nature row to be cascaded to the corresponding shopping_cart row.  Does the above indicate a bug, or am I doing this wrong?

Thanks.

Greg
--
| E R G O N O S I S
| Greg Ederer
| Lead Developer
| greg@ergonosis.com
| 360.379.1157
| 
| OpenDocument - OK
|