How MyBatis Uses Over 10 Design Patterns to Simplify ORM Architecture
The article analyzes MyBatis’s 20,000‑line source code, showing how it applies more than ten classic design patterns—such as Factory, Singleton, Builder, Adapter, Proxy, Composite, Decorator, Template, Strategy, and Iterator—to decouple complex ORM scenarios, improve extensibility, and illustrate practical implementation details.
Overview
MyBatis’s source code (~20,000 lines) makes extensive use of classic design patterns to decouple complex scenarios. The following sections describe the most important patterns, the key classes that implement them, and the typical usage contexts within the framework.
Factory Pattern
Purpose: Hide the concrete creation logic of SqlSession and related components.
Key class: SqlSessionFactory (simple‑factory). It creates SqlSession objects, configures the data‑source environment, builds a TransactionFactory, and assembles the SQL executor chain.
Related factories include ObjectFactory, MapperProxyFactory and DataSourceFactory.
Singleton Pattern
Purpose: Ensure a single configuration instance throughout the lifecycle of a MyBatis session.
Key class: Configuration. All mappings, caches, parameter handlers, interceptors, and object factories are stored here and are built during the SqlSessionFactoryBuilder phase.
Other singletons in the codebase include ErrorContext and LogFactory.
Builder Pattern
Purpose: Incrementally construct complex objects while keeping construction logic separate from business flow.
Key class: ResultMap.Builder (example). MyBatis contains many *Builder classes such as SqlSessionFactoryBuilder, XMLConfigBuilder, XMLMapperBuilder, XMLStatementBuilder, and CacheBuilder. These builders parse XML configuration files and assemble the corresponding runtime objects.
Adapter Pattern
Purpose: Provide a uniform logging API while supporting multiple underlying logging frameworks (Log4j, Log4j2, SLF4J).
MyBatis defines its own Log interface and supplies adapters that delegate calls to the concrete logging implementation selected at runtime.
Proxy Pattern
Purpose: Supply a placeholder that intercepts method calls on mapper interfaces and forwards them to the appropriate executor. MapperProxy implements each DAO interface at runtime. When a mapper method is invoked, the proxy creates a MapperMethod object, selects the correct Executor, executes the SQL, and returns the result.
Related classes: DriverProxy, Plugin, Invoker, MapperProxyFactory.
Composite Pattern
Purpose: Represent XML dynamic SQL tags as a tree of SqlNode objects, enabling a part‑whole hierarchy.
MyBatis provides nine dynamic tags ( trim, where, set, foreach, if, choose, when, otherwise, bind). Each tag implements SqlNode; composite nodes combine child nodes to form the final SQL statement.
Decorator Pattern
Purpose: Add caching behavior to the executor without modifying its core logic (also known as the Russian‑doll pattern).
The second‑level cache wraps a SimpleExecutor with a CachingExecutor. The decorator forwards calls to the underlying executor while managing cache reads/writes.
Template Pattern
Purpose: Define the skeleton of an algorithm in a base class while allowing subclasses to override specific steps. BaseExecutor provides the overall flow for query and update operations (open connection, create statement, execute, handle results, close). Subclasses such as SimpleExecutor, CachingExecutor, and BatchExecutor override the steps that differ.
Strategy Pattern
Purpose: Encapsulate algorithms for handling different JDBC types, allowing MyBatis to select the appropriate implementation at runtime.
Each TypeHandler (e.g., StringTypeHandler, LongTypeHandler, DateTypeHandler) implements a common interface. The framework chooses the handler based on the Java type of the parameter or result, eliminating large if‑else blocks.
Iterator Pattern
Purpose: Traverse a collection without exposing its internal representation. PropertyTokenizer implements an iterator over property tokens in a MetaObject. It is used throughout MyBatis for parsing nested property expressions, configuration strings, and dynamic SQL placeholders.
Conclusion
By cataloguing these patterns—Factory, Singleton, Builder, Adapter, Proxy, Composite, Decorator, Template, Strategy, and Iterator—we see how MyBatis solves complex ORM problems through systematic abstraction. Understanding these implementations provides valuable insight into architectural design and prepares developers for advanced engineering roles.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
