Design Patterns in MyBatis: Builder, Factory, Singleton, Proxy, Composite, Template Method, Adapter, Decorator, Iterator

This article examines how MyBatis applies classic design patterns—including Builder, Factory, Singleton, Proxy, Composite, Template Method, Adapter, Decorator, and Iterator—by analysing source code snippets and explaining each pattern's role in the framework's configuration, execution, caching, and dynamic SQL generation.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
Design Patterns in MyBatis: Builder, Factory, Singleton, Proxy, Composite, Template Method, Adapter, Decorator, Iterator

Although most developers know the 26 classic design patterns, they often remain at a conceptual level; reading MyBatis source code reveals many of these patterns in real use, deepening understanding of both the patterns and the framework.

1. Builder Pattern

The Builder pattern separates the construction of a complex object from its representation. In MyBatis, classes such as SqlSessionFactoryBuilder, XMLConfigBuilder, XMLMapperBuilder, XMLStatementBuilder, and CacheBuilder are typical builders that read configuration files, parse XML, create objects via reflection, and store results in caches.

public SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { ... }

During initialization, SqlSessionFactoryBuilder invokes XMLConfigBuilder, which in turn uses XMLMapperBuilder and XMLStatementBuilder to build the core Configuration object.

2. Factory Pattern

MyBatis uses a simple factory for objects such as SqlSessionFactory and ObjectFactory. The factory encapsulates object creation based on input parameters. public class MapperProxyFactory<T> { ... } The MapperProxyFactory creates a proxy for a mapper interface, delegating method calls to MyBatis runtime.

3. Singleton Pattern

Singleton ensures a class has only one instance. MyBatis applies this to ErrorContext (thread‑local singleton) and LogFactory (global logger factory).

public class ErrorContext { private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<>(); ... }

4. Proxy Pattern

Proxy is the core of MyBatis: a mapper interface is automatically proxied, so developers write only the interface while MyBatis handles SQL execution.

public class MapperProxy<T> implements InvocationHandler, Serializable { ... }

The invoke method decides whether to call the original method, a default method, or a MapperMethod that executes the SQL.

5. Composite Pattern

Composite treats individual and composite objects uniformly. MyBatis builds a tree of SqlNode objects (e.g., TrimSqlNode, IfSqlNode) to represent dynamic SQL.

public interface SqlNode { boolean apply(DynamicContext context); }

Leaf nodes such as TextSqlNode append raw SQL, while container nodes recursively apply their children.

6. Template Method Pattern

BaseExecutor

defines the skeleton of SQL execution and delegates specific steps to subclasses ( SimpleExecutor, ReuseExecutor, BatchExecutor).

protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;

Each executor implements the abstract methods to provide different statement handling strategies.

7. Adapter Pattern

MyBatis adapts various logging frameworks through the Log interface and concrete adapters such as Log4jImpl, Slf4jImpl, etc.

public class Log4jImpl implements Log { private Logger log; ... }

The adapter translates MyBatis logging calls to the underlying framework.

8. Decorator Pattern

Caching in MyBatis uses a core Cache interface (implemented by PerpetualCache) wrapped by decorators like FifoCache, LruCache, LoggingCache, SerializedCache, ScheduledCache, SoftCache, SynchronizedCache, and WeakCache. The decorator chain controls eviction, synchronization, logging, and serialization.

9. Iterator Pattern

The PropertyTokenizer class implements Iterator<PropertyTokenizer> to parse property strings (e.g., user.address[0].city) and iterate over each token.

public class PropertyTokenizer implements Iterator<PropertyTokenizer> { ... }

It provides hasNext() and next() methods to traverse the token hierarchy.

Source: http://crazyant.net/2022.html

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.

Design PatternsSoftware ArchitectureBackend DevelopmentMyBatis
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

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.