Cache doesn't return any hits on myBatis Java 3.0.3

35 views
Skip to first unread message

LisandroP

unread,
Dec 7, 2010, 3:36:36 PM12/7/10
to mybatis-user
Hello,

I'm working on a Java project using myBatis as its DB backend, and i
simply cannot get the cache to work properly - no matter what, it
returns zero hits on identical queries over the same transaction:

[07/12/2010 16:26:28] [DEBUG] Cache Hit Ratio [com.xxx.TestMapper]:
0.0

Right now i'm trying to debug the application, so the cache
configuration on the mappers are simply:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://
mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.xxx.TestMapper">
<cache size="100000" eviction="LRU"/>
<select id="testSelect" parameterType="String"
resultType="com.xxx.TestObject" useCache="true">
SELECT id, RelatedTable, Name, Description
FROM xxxx
WHERE UPPER(Name) = UPPER(#{name});
</select>
</mapper>

Data source is a PooleDataSource object using com.mysql.jdbc.Driver,
with a configuration generated by code; both the com.xxx.TestObject
alias and the com.xxx.TestMapper are initialized. In fact, the
application runs flawlessly besides the cache issues.

¿Any pointers on what could be the problem? Thanks in advance.

Clinton Begin

unread,
Dec 8, 2010, 11:11:36 AM12/8/10
to mybati...@googlegroups.com
Just to try... set the type to read-only and run your test again.

Clinton

LisandroP

unread,
Dec 8, 2010, 12:13:02 PM12/8/10
to mybatis-user
Yep. I've also tried every cache type with no results. Today i also
tried tracing the process' execution with a debugger, and i can
confirm that two identical queries generate the same CacheKey object,
but the getObject() call returns no items for it.

¿Could it be something i'm missing in the configuration? I've skipped
XMLs altogheter and i configured my MyBatis instance using the
Configuration class methods, as described on the documentation. This
is because my project requires to keep all the configuration
centralized on an external file - including database parameters.

I'd really love to paste some code here but since this is a commercial
project i'm unable to :( But, globally what i'm doing is:

- Instantiate an environment ("default"), using PooledDataSource over
a com.mysql.jdbc.Driver JDBC and a ManagedTransaction.
- Instantiate a Configuration object using this previous environment,
on which i've set cacheEnabled=true.
- Register aliases for all the classes that will hold query results
(registerAlias)
- Add all the mapper classes i'm using (addMapper)
- Instantiate a SQLSessionFactoryBuilder with this configuration
- Instantiate a SQLSession, which is the only one used through the
process (using ExecutorType.BATCH)

I've tried playing with the lazy loading options and useGeneratedKeys,
but nothing seems to make any difference.

Thanks in advance!

Clinton Begin

unread,
Dec 8, 2010, 9:13:52 PM12/8/10
to mybati...@googlegroups.com
If you step through the code, you'll also see any cache conditionals (like isCacheEnabled type booleans etc.)... but I think most of that is figured out at build time.  The caching is done via an executor proxy, so if you're seeing cache code at all while stepping through, it's enabled.  That said, you can dig pretty deep, and the caches are pretty easy to understand.  

One thing is that the cache is transactional.... so until you end a session, the cache may not be "committed" in some cases.... 

Try stepping through again, to see if you can spot the issue... it's hard for me to visualize without code.  :-)

Clinton

LisandroP

unread,
Dec 9, 2010, 8:26:42 AM12/9/10
to mybatis-user
> One thing is that the cache is transactional.... so until you end a session,
> the cache may not be "committed" in some cases....

Indeed, that was it. The "global" cache for the mapper won't be
updated until the current transaction (SQLSession) is closed. Since i
envisioned my process as a single, huge transaction, the cache was
effectively useless.

This behavior isn't described in the documentation, AFAIK. It would be
nice to have it clearly outlined there, as it is not immediately
apparent and it might led to a few head scratches. I know it did it
for me :)

So, right now i'm doing some rewrites to implement transactions which
solves my problem. By the way, ¿is there anyway of "commiting" the
cache on an open transaction? Perhaps it would be an useful addition
to the frameworks' API.

Again, thanks for the help. And thanks for all your hard work on
iBatis / MyBatis as well!

Larry Meadors

unread,
Dec 9, 2010, 10:02:50 AM12/9/10
to mybati...@googlegroups.com
IMO, this is a nice side-effect of using the SqlSessionManager -
because each operation is in it's own transaction (unless you start
one manually) the cache is constantly updated.

Larry

Reply all
Reply to author
Forward
0 new messages