mybatis cache enabled without aggressiveLazyLoading throws non serializable error

255 views
Skip to first unread message

David Stuart

unread,
Nov 11, 2010, 8:00:42 PM11/11/10
to mybatis-user
This is a summation of a previous thread which has now been narrowed
down to a single problem.

Using the mybatis-spring RC to load all my mappings, if I have the
cache enabled, lazyLoading enabled but turn off the
aggressiveLazyLoading the it throws a non serializable exception.

org.apache.ibatis.exceptions.PersistenceException:
### Error closing transaction. Cause:
org.apache.ibatis.cache.CacheException: Error serializing object.
Cause: java.io.NotSerializableException:
org.apache.ibatis.executor.loader.ResultLoaderMap$LoadPair
### Cause: org.apache.ibatis.cache.CacheException: Error serializing
object. Cause: java.io.NotSerializableException:
org.apache.ibatis.executor.loader.ResultLoaderMap$LoadPair

Either turning off the caching or turning on the aggressiveLazyLoading
fixes the problem.

It would appear that there is a problem with the ResultObjectProxy
that cglib creates being non serializable.

I have tried using ehcache as a substitute but it throws up another
error (can't find the mapping).

Any help would be greatly appreciated

David

Thomas Duffey

unread,
Nov 11, 2010, 10:51:46 PM11/11/10
to mybati...@googlegroups.com
Can't help but wanted to say my project recently experienced the same problem and exact same exception. My solution was to ditch mybatis lazyloading and implement my own @LazyLoad trickery.

Tom

--
Tom Duffey
tdu...@trillitech.com
414-915-3915

Clinton Begin

unread,
Nov 12, 2010, 1:10:11 AM11/12/10
to mybati...@googlegroups.com
That is odd indeed.  Especially because it happens when lazy loading is off... 

David Stuart

unread,
Nov 12, 2010, 6:45:37 AM11/12/10
to mybatis-user
just to clarify...

cache=true
lazyLoading=true
aggressiveLazyLoading=false

will throw the error.

Changing either the cache setting or the aggressiveLazyLoading means
it will work.

PS My old system used a hand rolled lazyLoad because of these kinds of
issues, but I had hoped to use the new dev would allow me to remove
that extra moving part

Clinton Begin

unread,
Nov 12, 2010, 11:00:32 AM11/12/10
to mybati...@googlegroups.com
Oh, thanks for clarifying.

This makes sense if you're using a cache that serializes objects.  This includes the read/write caches in iBATIS and many other caches.  

Unfortunately it's a bit of a limitation at this time.  I can only suggest that you use either caching or lazy loading (or enable aggressiveLazyLoading).  

They're all performance improvements, but together certain combinations can pose problems.  My personal preference is to write queries that return only exactly what I need... as this flexibility is an advantage that MyBatis has.  I would favor caching next, and finally I'd resort to lazy loading last.  

That said, this isn't an "excuse".  I think there should be a way to get this working.  However, it will take some thought.  The challenge is that the LoadPair class has references pretty deep into MyBatis, which includes even the datasource.  To fix this, we'll need a way to "disconnect" the objects from the environment. It's totally possible, but will require deciding on a VM or system level lookup (could be JNDI, could be a static variable in a class... etc.)

For the time being, I hope one of the existing configurations can work for you.

Cheers,
Clinton

Eduardo

unread,
Nov 12, 2010, 12:09:27 PM11/12/10
to mybatis-user
Clinton, maybe this issue (with patch) is related.

http://code.google.com/p/mybatis/issues/detail?id=110

David Stuart

unread,
Nov 12, 2010, 2:33:34 PM11/12/10
to mybatis-user
Clinton,

I can see your issue here, but it is certainly a surprise when a valid
combination of config settings (and probably one that would be quite
common) starts throwing exceptions. Especially as it is undocumented.

I also agree that there are other things that you can take care of to
speed up before you might end up with this combination of settings (N
+1 being the obvious example), but this would seem to me to be an
optimal version. Allowing you to both load those objects that are used
all the time through the cache (and within other objects) without
performance hit, whilst only loading those unfortunate N+1 queries
when required.

It also leads then to another question. Why have the both lazyLoading
and aggressiveLazyLoading settings at all. Since we can't have them
set to true and false respectively. Either they are both false and all
objects are loaded albeit without the cglib proxy or they are both
true and all objects are loaded.

Clinton Begin

unread,
Nov 12, 2010, 2:43:03 PM11/12/10
to mybati...@googlegroups.com
Combinations do work.  Unfortunately it's pretty difficult to determine at runtime whether the configuration is valid or not.  

Like I said, I'm not making excuses... it's a limitation.  It will take some thought as to how to deal with it.

The aggressiveLazyLoading is important for domain models that access other properties internally inside their getters and setters (e.g. getFullName() that uses firstName and lastName).

But not everyone likes aggressive lazy loading, because it's obviously a performance impact.

MyBatis has always been about flexibility... unfortunately using all of the features at once together, may not work in all cases, as in this one.

Clinton 

David Stuart

unread,
Nov 12, 2010, 3:50:57 PM11/12/10
to mybatis-user
No problem. I've used ibatis/mybatis with great love now in a nation
wide mission critical application since it's very very first
iterations (we've been live 24/7 for 8 years I think it is now). There
is no doubt that version 3 is a great version, it was just that this
config was very important to a new version of the application. Now
that the limitation is identified I can go about working around it
properly until an answer can be identidfied.
Reply all
Reply to author
Forward
0 new messages