Analysis of MyBatis First‑Level and Second‑Level Cache Mechanisms

The article thoroughly examines MyBatis’s first‑level (session) and second‑level (namespace) caches, detailing their configurations, internal workflows, source‑code implementations, experimental behaviors, common pitfalls such as stale or dirty data, and advises disabling built‑in caching in favor of dedicated solutions for production.

Meituan Technology Team
Meituan Technology Team
Meituan Technology Team
Analysis of MyBatis First‑Level and Second‑Level Cache Mechanisms

MyBatis is a widely used Java persistence framework. While its default cache configuration works for many scenarios, the cache mechanism has several shortcomings that can lead to dirty data and hidden risks.

This article examines MyBatis caching from both usage and source‑code perspectives, covering first‑level (session) cache and second‑level (namespace) cache, their configurations, workflows, and practical experiments.

Table of Contents

First‑level cache introduction and configuration

First‑level cache workflow and source‑code analysis

First‑level cache summary

Second‑level cache introduction and configuration

Second‑level cache source‑code analysis

Second‑level cache summary

Overall conclusion

First‑Level Cache

Introduction

When the same SQL statement is executed multiple times within a single SqlSession, MyBatis can serve the result from the first‑level cache, avoiding repeated database hits and improving performance.

Each SqlSession holds an Executor which contains a LocalCache. The cache lookup process is:

Generate a CacheKey from the statement ID, offset, limit, SQL text, and parameters.

Check LocalCache for the key.

If found, return the cached result; otherwise query the database and store the result in the cache.

Configuration

Enable the first‑level cache by setting <setting name="localCacheScope" value="SESSION"/> (default) or STATEMENT for a narrower scope.

<setting name="localCacheScope" value="SESSION"/>

Experiments

Various JUnit tests demonstrate cache behavior:

Experiment 1 : Three consecutive getStudentById(1) calls within the same session hit the cache after the first query.

Experiment 2 : An insert operation clears the first‑level cache, causing the subsequent query to hit the database.

Experiment 3 : Two separate SqlSessions share no cache; an update in one session does not affect the cache of the other, demonstrating session‑level isolation.

Workflow & Source‑Code Analysis

The core classes involved are SqlSession, Executor, BaseExecutor, CacheKey, and PerpetualCache. Key points include:

CacheKey construction uses statement ID, offset, limit, SQL, and parameters.

CacheKey equality checks the ordered list of these components.

BaseExecutor’s query first attempts to retrieve from localCache; if missing, it queries the database and writes back to the cache.

Update/insert/delete operations invoke clearLocalCache(), invalidating the first‑level cache.

Second‑Level Cache

Introduction

The second‑level cache shares cached data across multiple SqlSessions within the same namespace. When enabled, the query order becomes: second‑level cache → first‑level cache → database.

Configuration

Enable globally with <setting name="cacheEnabled" value="true"/> and declare a cache in each mapper XML: <cache/> Optional attributes include type, eviction, flushInterval, size, readOnly, and blocking. A cache‑ref can make different mappers share the same cache.

Experiments

Experiment 1 : Without committing the first session, the second session does not see cached data.

Experiment 2 : After committing the first session, the second session retrieves the result from the second‑level cache.

Experiment 3 : An update in another session invalidates the cache for the affected namespace.

Experiment 4 : Multi‑table queries can cause stale data because the second‑level cache is namespace‑scoped and does not react to changes in other namespaces.

Experiment 5 : Using cache‑ref to share a cache between namespaces solves the stale‑data issue but widens the cache granularity.

Source‑Code Analysis

The second‑level cache is implemented by CachingExecutor, which decorates BaseExecutor. The decorator chain is:

SynchronizedCache → LoggingCache → SerializedCache → LruCache → PerpetualCache.

Key methods: Cache cache = ms.getCache(); – obtain the cache associated with the mapped statement. flushCacheIfRequired(ms); – clears the cache for statements that require it (e.g., insert/update/delete).

During a query, tcm.getObject(cache, key) attempts to read from the transactional cache; on miss, the delegate executor is invoked and the result is stored via tcm.putObject(cache, key, list).

Commit triggers tcm.commit(), which flushes pending entries to the underlying cache and clears it if necessary.

Summary

First‑level cache lives for the duration of a SqlSession and is essentially an unbounded HashMap.

Second‑level cache extends caching across SqlSessions at the namespace level, but its default local implementation is not suitable for distributed environments.

Both caches can produce dirty data in multi‑session or multi‑table scenarios; careful configuration (e.g., using STATEMENT scope or disabling cache in production) is recommended.

Full Conclusion

The article provides a comprehensive walkthrough of MyBatis caching, including configuration, practical experiments, and deep source‑code inspection. For production systems, it is advisable to disable MyBatis’s built‑in cache and rely on dedicated caching solutions (e.g., Redis, Memcached) when needed.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaperformanceCacheMyBatisORM
Meituan Technology Team
Written by

Meituan Technology Team

Over 10,000 engineers powering China’s leading lifestyle services e‑commerce platform. Supporting hundreds of millions of consumers, millions of merchants across 2,000+ industries. This is the public channel for the tech teams behind Meituan, Dianping, Meituan Waimai, Meituan Select, and related services.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.