When using Mybatis cache, there are some points to consider.
Local session cache lifecycle
- Local session cache is enabled with default option
- Cache boundary is for all the queries within a SqlSession
- An item is cached when querying a record
- The item is reused when querying with the same parameter
- Cache is flushed when insert/update/delete is executed or when the SqlSession is closed
- When flushing cache, all cache items are deleted
Global cache (2nd level cache) lifecycle
- Global cache is on by explicit option
- Cache boundary is a mapper’s namespace (= all the sqls within the mapper file)
- An item is cached for queried data
- Cache items are cached when SqlSession.close(), commit() or rollback() (which is different from local cache)
- Cache flushing happens when SqlSession.close(), commit() or rollback()
- Cache flushing happens if insert/update/delete is executed, in that case, all queried data before insert/update/delete are deleted
- For example, query record 1 -> query record 2 -> update record 1 -> query record 3 happens, only record 3 is cached (record 1 and 2 are not cached because update is executed)
Some points to consider
- If you want to use global cache, split mapper into cache boundary (Don’t put all sqls into one mapper.xml)
- If insert/update/delete happens frequently, global cache is not recommended (It is diffecult to verify a cache’s lifecycle)
- Use local cache only if concurrent access to the same record does not happen
- If insert/update/delete happens frequently, local cache also is not recommended
- To sum up, I recommend not to use Mybatis cache (local or global) if you don’t understand it’s caching mechanism. Rather than, explicit logic (explicit cache api call or Spring @Transactional annotation) could be better solution