Skip to main content

Error cascading delete to child item (@OneToMany relationship)

10 replies [Last post]
edh
Offline
Joined: 2007-06-11

Hi all. I'm getting this error using the latest release of Glassfish Persistence (using Derby as the underlying database). I have an object called CachedItem, to which I've added a Collection of CachedItemReference objects. These represents any items that the CachedItem object reference. I've added the following methods to the CachedItem object

@OneToMany(mappedBy="cachedItem", cascade={CascadeType.PERSIST, CascadeType.REMOVE})
public Collection getReferencedItems() {
if (referencedItems == null) {
referencedItems = new java.util.HashSet();
}
return referencedItems;
}

public void setReferencedItems(final Collection references) {
Collection existingRefs = getReferencedItems();
if (!(existingRefs.isEmpty())) {
final Collection clone
= new java.util.HashSet(existingRefs);
for (CachedItemReference reference : clone) {
removeReference(reference);
}
}

for (CachedItemReference reference : references) {
addReference(reference);
}
}

public void addReference(CachedItemReference reference) {
getReferencedItems().add(reference);
reference.setCachedItem(this);
}

public void removeReference(CachedItemReference reference) {
getReferencedItems().remove(reference);
reference.setCachedItem(null);
}

The CachedItemReference object simply has the following method defined

@ManyToOne
public CachedItem getCachedItem() {
return cachedItem;
}

I've made these changes, then execute the new code against the existing test cases. We have some test cases that create, update and delete the CachedItem objects. When we attempt to delete the CachedItem object, the following exception is thrown:

Local Exception Stack:
Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0 (Build b50-beta3 (06/07/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: DELETE on table 'CACHED_ITEM' caused a violation of foreign key constraint 'CCHDTMRFRNCCCHDTMD' for key (1). The statement has been rolled back.
Error Code: 20000
Call: DELETE FROM REPLIB.CACHED_ITEM WHERE NOT EXISTS(SELECT t0.ID FROM REPLIB.CACHED_ITEM t0, REPLIB.CACHED_ITEM_VALUE t1 WHERE (t1.ID = t0.ID) AND t0.ID = REPLIB.CACHED_ITEM.ID)
Query: DeleteAllQuery()
at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:311)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:654)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:703)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:492)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:452)
at oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:690)
at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.deleteAll(DatasourceCallQueryMechanism.java:117)
at oracle.toplink.essentials.queryframework.DeleteAllQuery.executeDatabaseQuery(DeleteAllQuery.java:198)
at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:628)
at oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:555)
at oracle.toplink.essentials.queryframework.ModifyAllQuery.executeInUnitOfWork(ModifyAllQuery.java:168)
at oracle.toplink.essentials.queryframework.DeleteAllQuery.executeInUnitOfWork(DeleteAllQuery.java:124)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2233)
at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:952)
at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:924)
at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.executeUpdate(EJBQueryImpl.java:391)
at com.intecbilling.replib.cache.CacheService.removeAllFromFolder(CacheService.java:190)
at com.intecbilling.replib.cache.Cache.setContentForFolders(Cache.java:364)
at com.intecbilling.replib.CacheRepository.updateCachedItemsForFolders(CacheRepository.java:260)
at com.intecbilling.replib.CacheRepository.updateCacheForQuery(CacheRepository.java:157)
at com.intecbilling.replib.CacheRepository.findFiles(CacheRepository.java:274)
at com.intecbilling.replib.CacheRepository.findFiles(CacheRepository.java:267)
at com.intecbilling.replib.LocalConfigurationRepositoryTest.testCreateAndDelete(LocalConfigurationRepositoryTest.java:270)
Caused by: java.sql.SQLException: DELETE on table 'CACHED_ITEM' caused a violation of foreign key constraint 'CCHDTMRFRNCCCHDTMD' for key (1). The statement has been rolled back.
at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedConnection.handleException(Unknown Source)
at org.apache.derby.impl.jdbc.ConnectionChild.handleException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeStatement(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedPreparedStatement.executeUpdate(Unknown Source)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:647)
... 43 more
... Removed 21 stack frames

Now, I've looked at the SQL that Derby used to create the database schema objects, and it looks like

CREATE TABLE REPLIB.CACHED_ITEM (ID INTEGER GENERATED ALWAYS AS IDENTITY NOT NULL, LAST_MODIFIED TIMESTAMP, FOLDER VARCHAR(255) NOT NULL, PARSEABLE SMALLINT DEFAULT 0, TYPE VARCHAR(255), SECURITY_GROUP VARCHAR(255), NAME VARCHAR(255) NOT NULL, REPOSITORY VARCHAR(255) NOT NULL, VERSION INTEGER, ID_ATTRIBUTE INTEGER, PRIMARY KEY (ID))
CREATE TABLE REPLIB.CONFREP_RESERVATION (ID INTEGER GENERATED ALWAYS AS IDENTITY NOT NULL, REPOSITORY VARCHAR(255) NOT NULL, SYSTEM_ID VARCHAR(255) NOT NULL, VERSION INTEGER, CONFREP VARCHAR(255) NOT NULL, PRIMARY KEY (ID))
CREATE TABLE REPLIB.CACHED_ITEM_REFERENCE (ID INTEGER GENERATED ALWAYS AS IDENTITY NOT NULL, URL VARCHAR(255) NOT NULL, CACHEDITEM_ID INTEGER, PRIMARY KEY (ID))
CREATE TABLE REPLIB.CACHE_PROPERTY (NAME VARCHAR(255) NOT NULL, VALUE VARCHAR(255) NOT NULL, VERSION INTEGER, PRIMARY KEY (NAME))
CREATE TABLE REPLIB.CACHED_ITEM_VALUE (ID INTEGER NOT NULL, VALUE BLOB, PRIMARY KEY (ID))
ALTER TABLE REPLIB.CACHED_ITEM ADD CONSTRAINT UNQ_CACHED_ITEM_0 UNIQUE (REPOSITORY, FOLDER, NAME)
ALTER TABLE REPLIB.CONFREP_RESERVATION ADD CONSTRAINT UNQ_CONFREP_RESERVATION_0 UNIQUE (REPOSITORY, SYSTEM_ID)
ALTER TABLE REPLIB.CONFREP_RESERVATION ADD CONSTRAINT UNQ_CONFREP_RESERVATION_1 UNIQUE (REPOSITORY, CONFREP)
ALTER TABLE REPLIB.CACHED_ITEM_REFERENCE ADD CONSTRAINT CCHDTMRFRNCCCHDTMD FOREIGN KEY (CACHEDITEM_ID) REFERENCES REPLIB.CACHED_ITEM (ID)
ALTER TABLE REPLIB.CACHED_ITEM_VALUE ADD CONSTRAINT CACHEDITEM_VALUEID FOREIGN KEY (ID) REFERENCES REPLIB.CACHED_ITEM (ID)

So, the constraint CCHDTMRFRNCCCHDTMD is the index for the foreign key constraint in CACHED_ITEM_REFERENCE referencing back to CACHED_ITEM table.

The test case is just removing the CachedItem object from the entity manager, and is not doing anything with the child objects themselves. It seems to be attempting to delete the parent item before deleting the child items? Is this right?

One odd thing I found was, when trying to figure out what's going on, I added a @PreRemove method to the CachedItem object, like this....

@PreRemove
public void preRemove() {
System.out.println("Clearing references");
setReferencedItems(NO_REFERENCES);
}

Thinking I could clear the child object references myself. But this is never executed (from what I can tell)?

Am I doing something wrong? Or is this a continuation of some of the prevous bugs that were fixed in releases 45 and 47?

Thanks for any help,
Ed

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
edh
Offline
Joined: 2007-06-11

Just an update. If I update the code using the JPA entities to remove all the references for the items about to be removed, then my test cases all pass.

So, I guess my original questions are still there, though. I was under the impression that using cascaseType.REMOVE would cascade remove calls to the child items. Is the default to perform this after the parent item is removed? Also, am I setting up the @PreRemove call wrong? It's a bit of a worry that it didn't seem to get called (from what I can tell.... I'll accept I may be doing something wrong. :) )

Thanks for any info,
Ed

msell
Offline
Joined: 2007-07-16

According to the spec, using "cascadeType.REMOVE" (or ALL) should result in the deletion of children (and entries in the join table, if applicable) when calling "remove" on the parent.

I'm finding that TopLink does not actually do this, at least as of "Sun Java System Application Server 9.1 (build b52-rc)". There is an issue logged (1597) where this problem is claimed as resolved as of build 45, but apparently it has not yet been included.

I am able to reproduce this problem - if I call "remove" on a parent, the database reports an error when the row in the child's table is removed but the entry in the join table is not. The only workaround until this is fixed is to remove the reference in the collection, update the parent, remove the child, and then you may remove the parent.

mf125085
Offline
Joined: 2005-03-29

The fix is included since b45. Please post your relationship mapping!

msell
Offline
Joined: 2007-07-16

The relationship:

@OneToMany(cascade = CascadeType.ALL)
@JoinTable(name = Constants.TABLE_PREFIX + "asset_parameter")
private List parameters;

The error:

[#|2007-07-16T17:25:07.104-0700|WARNING|sun-appserver9.1|oracle.toplink.essentials.session.file:/D:/Development/apps/GlassFish/2/glassfish/domains/domain1/applications/j2ee-modules/metbase-1.0-SNAPSHOT/-metbase-ds.transaction|_ThreadID=18;_ThreadName=httpSSLWorkerThread-8080-1;_RequestID=7f55427c-a7b9-4664-a91a-56dbd01a82a8;|
Local Exception Stack:
Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0 (Build b52-rc (06/20/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: update or delete on "fluke_metbase_parameter" violates foreign key constraint "fk_fluke_metbase_asset_parameter_parameters_id" on "fluke_metbase_asset_parameter"
Detail: Key (id)=(360) is still referenced from table "fluke_metbase_asset_parameter".
Error Code: 0
Call: DELETE FROM fluke_metbase_parameter WHERE ((ID = ?) AND (vers_optlock = ?))
bind => [360, 1]
Query: DeleteObjectQuery(com.fluke.metbase.Parameter@168)
at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:311)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:654)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:703)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:492)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:452)
at oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:690)
at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:214)
at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.deleteObject(DatasourceCallQueryMechanism.java:205)
at oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.deleteObject(StatementQueryMechanism.java:130)
at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.deleteObjectForWrite(DatabaseQueryMechanism.java:258)
at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeCommit(DeleteObjectQuery.java:98)
at oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.executeWrite(DatabaseQueryMechanism.java:335)
at oracle.toplink.essentials.queryframework.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:111)
at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:628)
at oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:555)
at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:138)
at oracle.toplink.essentials.queryframework.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:125)
at oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:110)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2233)
at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:952)
at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:909)
at oracle.toplink.essentials.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:338)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1047)
at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:403)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1126)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:2443)
at oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:202)
at oracle.toplink.essentials.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:131)
at oracle.toplink.essentials.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:91)
at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:419)
at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:371)
at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:3781)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:3560)
at com.sun.ejb.containers.WebServiceInvocationHandler.invoke(WebServiceInvocationHandler.java:200)
at $Proxy229.deleteAsset(Unknown Source)
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:597)
at com.sun.enterprise.webservice.InvokerImpl.invoke(InvokerImpl.java:81)
at com.sun.enterprise.webservice.EjbInvokerImpl.invoke(EjbInvokerImpl.java:88)
at com.sun.xml.ws.server.InvokerTube$2.invoke(InvokerTube.java:132)
at com.sun.xml.ws.server.sei.EndpointMethodHandler.invoke(EndpointMethodHandler.java:241)
at com.sun.xml.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:74)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:559)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:518)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:503)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:400)
at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:70)
at com.sun.enterprise.webservice.MonitoringPipe.process(MonitoringPipe.java:147)
at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:79)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:559)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:518)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:503)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:400)
at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:70)
at com.sun.enterprise.webservice.CommonServerSecurityPipe.processRequest(CommonServerSecurityPipe.java:218)
at com.sun.enterprise.webservice.CommonServerSecurityPipe.process(CommonServerSecurityPipe.java:129)
at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:79)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:559)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:518)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:503)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:400)
at com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:229)
at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:430)
at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:230)
at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:121)
at com.sun.enterprise.webservice.Ejb3MessageDispatcher.handlePost(Ejb3MessageDispatcher.java:113)
at com.sun.enterprise.webservice.Ejb3MessageDispatcher.invoke(Ejb3MessageDispatcher.java:87)
at com.sun.enterprise.webservice.EjbWebServiceServlet.dispatchToEjbEndpoint(EjbWebServiceServlet.java:200)
at com.sun.enterprise.webservice.EjbWebServiceServlet.service(EjbWebServiceServlet.java:129)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
at com.sun.enterprise.web.AdHocContextValve.invoke(AdHocContextValve.java:114)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:87)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:624)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:268)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:631)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:562)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:803)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:339)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:261)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:212)
at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on "fluke_metbase_parameter" violates foreign key constraint "fk_fluke_metbase_asset_parameter_parameters_id" on "fluke_metbase_asset_parameter"
Detail: Key (id)=(360) is still referenced from table "fluke_metbase_asset_parameter".
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1548)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1316)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:191)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:452)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:351)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:305)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:647)
... 95 more
|#]

mf125085
Offline
Joined: 2005-03-29

Looks like you hit a known issue, which is documented under
https://glassfish.dev.java.net/issues/show_bug.cgi?id=2991

In your situation, the class mapped to the table fluke_metbase_parameter is the non-owning side of the relationship. Toplink executes removals in reverse lexical order of the class names, causing removals on fluke_metbase_parameter to be executed first.

The workarounds are:
1) Re-name the classes, so that the owning side is lexically later then fluke_metbase_parameter
2) Keep cascade = ALL, but remove the relationships *after* removing the owning side
3) Don't use cascade=REMOVE, and cascade the removal in your code.

msell
Offline
Joined: 2007-07-16

Thanks for the reply. I didn't see that issue in my searches - must not have searched "hard enough"...

: )

I've been removing the relationship in the collection first, then removing the children and then the parent as a workaround. I'll keep an eye on the issue in the meantime.

Thanks!

vladperl
Offline
Joined: 2004-08-11

> searches - must not have searched "hard enough"...

I also didn't find this issue.

It should be called: "cascading remove doesn't work except for ..."

Mayor problem not with the name but with approach how issues handle by the team.

Something wrong with this team I just can't believe that this issue has priority 4.

It was reported in May and still they didn't fix it.

Maybe they forgot that Glassfish has beta 3 status and soon will become RC.

Probably that the reason they put so low priority for this issue.

By the way it doesn't work also for @OneToOne relationship.

But after team had pending issue with query hint refresh during 7 months I shouldn't expect much from them ;)

Maybe I should start switch to different persistence provider after all.



Sincerely,

Vladimir

mf125085
Offline
Joined: 2005-03-29

Hi Ed,

looks like you execute a Bulk Delete. Bulk operations don't cascade to related objects. Please see section 4.10 "Bulk Update and Delete Operations" in the JPA spec. Bulk operation directly affect the database and also don't trigger life cycle callbacks for the same reason.

edh
Offline
Joined: 2007-06-11

Yes, the code is calling a Named Query which performs the delete. That would explain it. I'll check out the provided link and make sure I'm doing what it says. :)

Thanks heaps!

Ed

edh
Offline
Joined: 2007-06-11

I understand now. I will have to perform bulk-updates of the child items whenever we perform bulk updates of the parent items. Fortunately, we have this contained within a single class, so this isn't too hard.

Thanks for pointing me in the right direction!

Ed