|
Attached test case shows that after deleting via query, L2 cache still maintains a copy and em.find() finds the instance.
What happens if the user modifies the object or if the user obtains a read lock on the instance?
Added a trace output of the test case that is failing.
shows that the deleted instance (PObject-4501) is in L2 Cache. Please note the instance was locked and modified *after* delete by query (as we still has its reference). Does that give the cache a chance to heal? Please note that PObject-4501 has a DetachedStateManager when we lock/modify it after delete. I haven't looked at your test, but I'm guessing that since it has a DetachedStateManager, it's the same instance that you had been using earlier.
I would expect that if you deleted some instances with a bulk delete, then looked up an instance that had been deleted via a data cache hit, then tried to do anything involving a lock with that instance, you'd get a failure at commit time (assuming optimistic transactions and a @Version column). ... to finish that thought, I'd then expect that the instance would get cleared from the cache due to the optimistic lock failure, and a second transaction involving the instance (a newly-looked-up copy) would succeed.
Right -- a newly looked up copy (the copy comes out of L2 cache and not from the database where it really do not exist anymore) -- is essentially not usable i.e. any commit set containing that object fails. The L2 cache heals as soon as the commit fails.
So let me summarize a) delete via query leaves a copy in the L2 cache b) the cached copy can be located via em.find() c) however, any modify operation on this ghost copy will fail d) this failure will signal to clear the copy from the L2 cache. Do you think, it is worth mentioning in the doc? Well, I think that it's worth *fixing*, and shouldn't really be all that hard, either. But, assuming that we can't prioritize it appropriately to fix it, we should document it prior to the next release, yes.
I agree this bug is worth fixing and pending the fix, worth documenting as a bug. I'd be against documenting it as a "feature".
> b) When openjpa.datacache=false, the application can still obtain a
> non-null reference to StoreCache, however its delegate is null. > What should OpenJPAEntityManagerFactory.getStoreCache() return > when openjpa.datacache=false ? I think that this is fine behavior. You generally shouldn't need to get the StoreCache's delegate. The current behavior is nice because user code doesn't need to check whether or not a cache is active; instead, user code can just perform cache operations. Sure, they're no-ops when the cache isn't on, but that's fine. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
a) When datacache is active, even after an instance is deleted via query, the entitymanager is committed and cleared, EntityManager find() finds the instance -- not from its L1 cache but from its L2 cache.
If this is a known limitation -- it should be documented (could not find it in OpenJPA User's guide)
b) When openjpa.datacache=false, the application can still obtain a non-null reference to StoreCache, however its delegate is null.
What should OpenJPAEntityManagerFactory.getStoreCache() return when openjpa.datacache=false ?
c) delete directly i.e. em.remove() does the 'right' thing i.e. subsequent em.find() returns null.
d) Setting "openjpa.BrokerImpl" to "EvictFromDataCache=true" did not change the behavior (nor was expected)
The observations are based on the attached TestCase