change then remove results in exception... why [message #386072] |
Fri, 27 March 2009 05:13  |
Eclipse User |
|
|
|
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 #386079 is a reply to message #386077] |
Mon, 30 March 2009 11:32  |
Eclipse User |
|
|
|
> 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.
I cannot force the user these constraints; he may first change an object, then delete it.
For now I have solve this using deferred constraints, but I'll try that perform delete first option.
Tom
|
|
|
Powered by
FUDForum. Page generated in 0.03995 seconds