Topics

Dirty Objects in L2Cache (JPA)


passignat@...
 

I faced the bellow "issue" while detaching a query result. An application fix is to desactivate the L2Cache.

Cannot make object non-transactional since object is dirty

org.datanucleus.exceptions.NucleusUserException: Cannot make object non-transactional since object is dirty
	at org.datanucleus.api.jpa.state.PersistentDirty.transitionMakeNontransactional(PersistentDirty.java:64)
	at org.datanucleus.state.StateManagerImpl.makeNontransactional(StateManagerImpl.java:1008)
	at org.datanucleus.ExecutionContextImpl.getObjectFromLevel2Cache(ExecutionContextImpl.java:5154)
	at org.datanucleus.ExecutionContextImpl.getObjectFromCache(ExecutionContextImpl.java:5034)
	at org.datanucleus.ExecutionContextImpl.findObject(ExecutionContextImpl.java:3150)
	at org.datanucleus.store.rdbms.query.PersistentClassROF.findObjectWithIdAndLoadFields(PersistentClassROF.java:477)
	at org.datanucleus.store.rdbms.query.PersistentClassROF.getObject(PersistentClassROF.java:383)
	at org.datanucleus.store.rdbms.query.ForwardQueryResult.nextResultSetElement(ForwardQueryResult.java:181)
	at org.datanucleus.store.rdbms.query.ForwardQueryResult$QueryResultIterator.next(ForwardQueryResult.java:409)
	at org.datanucleus.store.rdbms.query.ForwardQueryResult.processNumberOfResults(ForwardQueryResult.java:137)
	at org.datanucleus.store.rdbms.query.ForwardQueryResult.advanceToEndOfResultSet(ForwardQueryResult.java:165)
	at org.datanucleus.store.rdbms.query.ForwardQueryResult.toArray(ForwardQueryResult.java:532)
	at org.datanucleus.api.jpa.JPAEntityManager.detach(JPAEntityManager.java:773)
	at org.datanucleus.api.jpa.JPAEntityManager.detach(JPAEntityManager.java:748)


The analysis (looking in the StateManager, which field is dirty) shows a date field (SCO) appears dirty.

I Tried the following (from old JDO memories) but no luck
if (this.startDate==null) {
this.startDate = startDate;
}else{
this.startDate.setTime(startDate.getTime());
}
I tried also to initialize the Date at object creation but no more luck.

I tried to chenage detach properties, with no luck
datanucleus.detachAsWrapped=true
datanucleus.DetachAllOnCommit=true
datanucleus.detachAllOnRollback=true

Any suggestions ?



Andy
 

No object in the L2 cache is "dirty" since there are no actual objects there ... just Map representations of them (CachedPC in the code).
How your object is created/initialised from the L2 cached object is where something is made dirty, and only you see that code. It isn't down to "luck".

Deactivating the L2 cache is clearly a bad "solution".


passignat@...
 

"No object in the L2 cache is "dirty" since there are no actual objects there ..."
=> Yes I checked that out up-front. You're right doing this, that's probably the only correct L2 cache implementation. (another good reason to choose DN)

"How your object is created/initialised from the L2 cached object is where something is made dirty"
Ok I get it. It's due to a PostLoad cleaning number (floating point errors when it's loaded from the db). I didn't identified correctly the dirty field... 

Deactivating the L2 cache is clearly a bad "solution".
Bad, there are some matter of discussion ;-) This subject may requires some thinking (eviction strategy, application load, cache size, deployment, datamodel complexity, concurrency, ...) before considering a broad usage... I faced some crazy applications around the world with another JDO product years ago. For some customers or part of their applications, at the end we preferred to have an efficient graph loading to the L2 cache, and for others it was the opposite...

But I agree, having a L2Cache is really important. For a part of the applications I'm working on actually, sure L2Cache will be an amazing performance improvement.


Thanks,
--
Stephane