cascade delete not working when cache is active [message #527823] |
Fri, 16 April 2010 10:57  |
Eclipse User |
|
|
|
We have a simple many to many setup done as two one-to-many: user - user2group - group with cascade delete. If we try to invoke the cascade delete in a simple unittest, then we get an exception.
The unit test only runs correctly when all caching is disabled (when the lines marked with --> below are enabled).
Why does the cache cause problems here?
[EL Warning]: 2010-04-16 16:42:03.734--UnitOfWork(849296)--Thread(Thread[main,5,main] )--Local Exception Stack:
Exception [EclipseLink-7251] (Eclipse Persistence Services - 1.2.0.v20091016-r5565): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [nl.knowledgeplaza.profiler.engine.model.User2Group] is mapped to a primary key column in the database. Updates are not allowed.
at org.eclipse.persistence.exceptions.ValidationException.prima ryKeyUpdateDisallowed(ValidationException.java:2372)
at org.eclipse.persistence.mappings.foundation.AbstractDirectMa pping.writeFromObjectIntoRowWithChangeRecord(AbstractDirectM apping.java:1228)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.b uildRowForUpdateWithChangeSet(ObjectBuilder.java:1070)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechan ism.updateObjectForWriteWithChangeSet(DatabaseQueryMechanism .java:1104)
at org.eclipse.persistence.queries.UpdateObjectQuery.executeCom mitWithChangeSet(UpdateObjectQuery.java:84)
at org.eclipse.persistence.internal.queries.DatabaseQueryMechan ism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:28 6)
at org.eclipse.persistence.queries.WriteObjectQuery.executeData baseQuery(WriteObjectQuery.java:58)
at org.eclipse.persistence.queries.DatabaseQuery.execute(Databa seQuery.java:670)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitO fWork(DatabaseQuery.java:589)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.execu teInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery. java:109)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.execu teInUnitOfWork(ObjectLevelModifyQuery.java:86)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.int ernalExecuteQuery(UnitOfWorkImpl.java:2858)
at org.eclipse.persistence.internal.sessions.AbstractSession.ex ecuteQuery(AbstractSession.java:1225)
at org.eclipse.persistence.internal.sessions.AbstractSession.ex ecuteQuery(AbstractSession.java:1207)
at org.eclipse.persistence.internal.sessions.AbstractSession.ex ecuteQuery(AbstractSession.java:1167)
at org.eclipse.persistence.internal.sessions.CommitManager.comm itChangedObjectsForClassWithChangeSet(CommitManager.java:233 )
at org.eclipse.persistence.internal.sessions.CommitManager.comm itAllObjectsForClassWithChangeSet(CommitManager.java:163)
at org.eclipse.persistence.internal.sessions.CommitManager.comm itAllObjectsWithChangeSet(CommitManager.java:116)
at org.eclipse.persistence.internal.sessions.AbstractSession.wr iteAllObjectsWithChangeSet(AbstractSession.java:3260)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.com mitToDatabase(UnitOfWorkImpl.java:1400)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUni tOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:521)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.com mitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1505)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUni tOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java: 200)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.com mitAndResume(UnitOfWorkImpl.java:1126)
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 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAcce ssorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMe thodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at nl.knowledgeplaza.util.jpa.EntityTransactionExtender.invoke( EntityTransactionExtender.java:86)
at $Proxy10.commit(Unknown Source)
at nl.knowledgeplaza.profiler.engine.unittest.Unittest.testCrea teAndCascadeDelete(Unittest.java:178)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAcce ssorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMe thodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall( FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(Refl ectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(Fr ameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate( InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(Ru nBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(Run Afters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit 4ClassRunner.java:73)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit 4ClassRunner.java:46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java :180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java: 41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java: 173)
at org.junit.internal.runners.statements.RunBefores.evaluate(Ru nBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(Run Afters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.r un(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(Test Execution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTe sts(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTe sts(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(R emoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main( RemoteTestRunner.java:197)
User:
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY, targetEntity = nl.knowledgeplaza.profiler.engine.model.User2Group.class, cascade = {CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE, CascadeType.REMOVE} )
volatile protected java.util.List<nl.knowledgeplaza.profiler.engine.model.User2Group > user2GroupsWhereIAmUser = new java.util.ArrayList<nl.knowledgeplaza.profiler.engine.model.User2Group >();
Group:
@OneToMany(mappedBy = "group", fetch = FetchType.LAZY, targetEntity = nl.knowledgeplaza.profiler.engine.model.User2Group.class, cascade = {CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE, CascadeType.REMOVE} )
volatile protected java.util.List<nl.knowledgeplaza.profiler.engine.model.User2Group > user2GroupsWhereIAmGroup = new java.util.ArrayList<nl.knowledgeplaza.profiler.engine.model.User2Group >();
User2Group:
@ManyToOne(fetch = FetchType.LAZY, targetEntity = nl.knowledgeplaza.profiler.engine.model.User.class, cascade = {CascadeType.REFRESH} ) @JoinColumn(name="user_id")
volatile protected nl.knowledgeplaza.profiler.engine.model.User user;
The unittest does this:
@org.junit.Test
public void testCreateAndCascadeDelete()
{
// get the EM
EntityManager lEntityManager = EclipselinkSetup.createEntityManager(cEntityManagerFactory);
try
{
// create entity
lEntityManager.getTransaction().begin();
// user
User lUser = new User().withUsername("testCreateAndDelete");
lEntityManager.persist(lUser);
// group
Group lGroup = new Group("testCreateAndDelete", "testCreateAndDelete");
lEntityManager.persist(lGroup);
// user2group
User2Group lUser2Group = new User2Group(lUser, lGroup);
lEntityManager.persist(lUser2Group);
// commit
lEntityManager.getTransaction().commit();
--> //lEntityManager.clear();
// cascade delete
lEntityManager.getTransaction().begin();
lEntityManager.remove(lEntityManager.merge(lGroup));
lEntityManager.getTransaction().commit();
// user2group should be gone as well
lUser2Group = User2Group.findByPK(lUser2Group.getId());
org.junit.Assert.assertNull(lUser2Group);
// but user not
lUser = User.findByPK(lUser.getId());
org.junit.Assert.assertNotNull(lUser);
}
finally
{
}
}
To be complete, here is the creation of the EMF and EM:
static public EntityManagerFactory createEntityManagerFactory(Class databasePlatform, Class jdbcDriver, String jdbcUrl, String jdbcUsr, String jdbcPwd, Map<String, Object> options)
{
if (log4j.isInfoEnabled()) log4j.info("Creating an EntityManagerFactory to " + jdbcUsr + " @ " + nl.knowledgeplaza.util.jdbc.Driver.PREFIX + jdbcDriver.getName() + "#" + jdbcUrl);
// setup the factory
Map<String, Object> lOptions = new HashMap<String, Object>();
// always use KPUTIL JDBC Driver so it will automatically log SQL to log4j
lOptions.put(PersistenceUnitProperties.JDBC_DRIVER, nl.knowledgeplaza.util.jdbc.Driver.class.getName());
lOptions.put(PersistenceUnitProperties.JDBC_URL, nl.knowledgeplaza.util.jdbc.Driver.PREFIX + jdbcDriver.getName() + "#" + jdbcUrl);
lOptions.put(PersistenceUnitProperties.JDBC_USER, jdbcUsr);
lOptions.put(PersistenceUnitProperties.JDBC_PASSWORD, jdbcPwd);
lOptions.put(PersistenceUnitProperties.TARGET_DATABASE, (databasePlatform == null? null : databasePlatform.getName()));
lOptions.put(PersistenceUnitProperties.TARGET_SERVER, TargetServer.None);
--> //lOptions.put(PersistenceUnitProperties.CACHE_SHARED_DEFAUL T, "false");
lOptions.put(PersistenceUnitProperties.LOGGING_LEVEL, "fine");
lOptions.put(PersistenceUnitProperties.LOGGING_EXCEPTIONS, "true");
lOptions.put(PersistenceUnitProperties.JDBC_SEQUENCE_CONNECT ION_POOL, "true"); // force sequences to use a separate pool
if (options != null) lOptions.putAll(options);
// setup the factory
EntityManagerFactory lEntityManagerFactory = Persistence.createEntityManagerFactory("kpprofiler", lOptions);
// done
return lEntityManagerFactory;
}
/**
*
*/
static public EntityManager createEntityManager(EntityManagerFactory entityManagerFactory)
{
Map<String, String> lOptions = new HashMap<String, String>();
EntityManager lEntityManager = EntityManagerExtender.wrap( entityManagerFactory.createEntityManager(lOptions) );
// make sure all entitymanagers have flushmode commit
lEntityManager.setFlushMode(FlushModeType.COMMIT);
// done
return lEntityManager;
}
|
|
|
|
Re: cascade delete not working when cache is active [message #528221 is a reply to message #528127] |
Mon, 19 April 2010 13:31  |
Eclipse User |
|
|
|
> What is missing is the User2Group mappings to Id that are involved in
> the exception. Since you only show the User<->User2Group relations,
> could the User2Group->Group be using its ID field? Please show the
> User2Group and verify that when you pass in User and Group in its
> constructor you are setting both sides of the bi directional relationships.
I'm setting both sides (its a reversed engineered fully connected BM). Otherwise with cache disabled it shouldn't work either. But I'll get the full definitions.
|
|
|
Powered by
FUDForum. Page generated in 0.05343 seconds