change then remove results in exception... why [message #386072] |
Fri, 27 March 2009 09:13 |
Tom Eugelink Messages: 825 Registered: July 2009 |
Senior Member |
|
|
Consider the following scenarion (in my standalone fat client, so it is not using burst database changes): an entity is fetched from the database, then a change is made to the entity (making it actually invalid to be stored in the database) and then the entity is removed. Below is a small test case.
// entitymanagerfactory
EntityManagerFactory lEntityManagerFactory = ...
// entitymanager
EntityManager lEntityManager = lEntityManagerFactory.createEntityManager();
// emulate user entry
Article2Storage lArticle2Storage = Article2Storage.findByPK(229277);
lArticle2Storage.setArticle(null); // this is not allowed, a N-M record must have both keys
lEntityManager.remove(lArticle2Storage); // now remove it
// commit
lEntityManager.getTransaction().begin();
lEntityManager.getTransaction().commit();
// close shop
lEntityManager.close();
lEntityManagerFactory.close();
This results in the following exception:
2009-03-27 10:00:57,296 DEBUG org.tbee.util.jdbc.PreparedStatement.invoke(PreparedStatemen t.java:139) #14992216[C24016891]: executeUpdate: UPDATE article2storage SET articlenr = ?, dwhmodified = ?, dwhby = ?, lazylock = ? WHERE ((oidnr = ?) AND (lazylock = ?))
[EL Warning]: 2009.03.27 10:00:57.578--UnitOfWork(25928160)--Local Exception Stack:
Exception [EclipseLink-4002] (Eclipse Persistence Services - 1.0.2 (Build 20081024)): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Cannot insert a null into column (article2storage.articlenr).
Error Code: -391
Call: UPDATE article2storage SET articlenr = ?, dwhmodified = ?, dwhby = ?, lazylock = ? WHERE ((oidnr = ?) AND (lazylock = ?))
bind => [null, 2009-03-27 10:00:38.984, 1, 2, 229277, 1]
Query: UpdateObjectQuery(nl.reinders.bm.Article2Storage@198f2a6, Oidnr=229277)
at org.eclipse.persistence.exceptions.DatabaseException.sqlExce ption(DatabaseException.java:313)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAcce ssor.executeDirectNoSelect(DatabaseAccessor.java:757)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAcce ssor.executeNoSelect(DatabaseAccessor.java:823)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAcce ssor.basicExecuteCall(DatabaseAccessor.java:557)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAcce ssor.executeCall(DatabaseAccessor.java:500)
at org.eclipse.persistence.internal.sessions.AbstractSession.ex ecuteCall(AbstractSession.java:855)
at org.eclipse.persistence.internal.sessions.IsolatedClientSess ion.executeCall(IsolatedClientSession.java:132)
at org.eclipse.persistence.internal.queries.DatasourceCallQuery Mechanism.executeCall(DatasourceCallQueryMechanism.java:204)
at org.eclipse.persistence.internal.queries.DatasourceCallQuery Mechanism.executeCall(DatasourceCallQueryMechanism.java:190)
at org.eclipse.persistence.internal.queries.DatasourceCallQuery Mechanism.updateObject(DatasourceCallQueryMechanism.java:681 )
at org.eclipse.persistence.internal.queries.StatementQueryMecha nism.updateObject(StatementQueryMechanism.java:431)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechan ism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism .java:1142)
at org.eclipse.persistence.queries.UpdateObjectQuery.executeCom mitWithChangeSet(UpdateObjectQuery.java:84)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechan ism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:29 0)
at org.eclipse.persistence.queries.WriteObjectQuery.executeData baseQuery(WriteObjectQuery.java:58)
at org.eclipse.persistence.queries.DatabaseQuery.execute(Databa seQuery.java:666)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitO fWork(DatabaseQuery.java:585)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.execu teInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery. java:114)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.execu teInUnitOfWork(ObjectLevelModifyQuery.java:86)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.int ernalExecuteQuery(UnitOfWorkImpl.java:2587)
at org.eclipse.persistence.internal.sessions.AbstractSession.ex ecuteQuery(AbstractSession.java:1178)
at org.eclipse.persistence.internal.sessions.AbstractSession.ex ecuteQuery(AbstractSession.java:1162)
at org.eclipse.persistence.internal.sessions.AbstractSession.ex ecuteQuery(AbstractSession.java:1108)
at org.eclipse.persistence.internal.sessions.CommitManager.comm itChangedObjectsForClassWithChangeSet(CommitManager.java:297 )
at org.eclipse.persistence.internal.sessions.CommitManager.comm itAllObjectsForClassWithChangeSet(CommitManager.java:228)
at org.eclipse.persistence.internal.sessions.CommitManager.comm itAllObjectsWithChangeSet(CommitManager.java:185)
at org.eclipse.persistence.internal.sessions.AbstractSession.wr iteAllObjectsWithChangeSet(AbstractSession.java:3129)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.com mitToDatabase(UnitOfWorkImpl.java:1241)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUni tOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:478)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.com mitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1330)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUni tOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java: 159)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.com mitAndResume(UnitOfWorkImpl.java:1002)
at org.eclipse.persistence.internal.jpa.transaction.EntityTrans actionImpl.commitInternal(EntityTransactionImpl.java:84)
at org.eclipse.persistence.internal.jpa.transaction.EntityTrans actionImpl.commit(EntityTransactionImpl.java:63)
at nl.reinders.bm.BMTestToplink.main(BMTestToplink.java:116)
As it turns out, even though entity has been removed, the change is still being persisted. I'm a bit uncertain about this. On the one hand I can imagine that Eclipselink simply keeps a list of changes and executes them. On the other hand, AFAIK that is not the case, but a copied model is created. If N-M entity was removed, there is no use in persisting it.
Even if I remove both key-entities, making the entity unreachable for persistence-via-relation, the exception remains:
// emulate user entry
Article2Storage lArticle2Storage = Article2Storage.findByPK(229277);
lArticle2Storage.setArticle(null);
lArticle2Storage.setStorage(null);
lEntityManager.remove(lArticle2Storage);
So the question: if an entity is removed, why are changes to it still persisted?
|
|
|
|
Re: change then remove results in exception... why [message #386077 is a reply to message #386072] |
Mon, 30 March 2009 14:04 |
|
The main reason for updating an object before deleting it is that this is
sometimes required. If your object has a constraint or dependency on
another object, if must be updated in order to be deleted. So, we must
allow an object to be updated before deletion.
In could be possible to make this a configurable option, so if you think
you never need to update an object being deleted run could set this
option, so you may wish to log an enhancement request for this. We do
already have the existing option "perform deletes first" which has a
similar effect. However, in general it is best if you do not change any
objects that you do not want updated, then you will have no issues.
---
James
http://www.nabble.com/EclipseLink---Users-f26658.html
James : Wiki : Book : Blog : Twitter
|
|
|
|
Powered by
FUDForum. Page generated in 0.04169 seconds