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