Databases 12 min read

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.

Top Architect
Top Architect
Top Architect
How MyBatis Uses Over 10 Design Patterns to Simplify ORM Architecture

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.

SqlSessionFactory structure
SqlSessionFactory structure

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.

Configuration singleton
Configuration singleton

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.

ResultMap builder
ResultMap builder

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.

Logging adapter hierarchy
Logging adapter hierarchy

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.

Mapper proxy structure
Mapper proxy structure

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.

SqlNode composite structure
SqlNode composite structure

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.

Caching executor decorator
Caching executor decorator

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.

BaseExecutor template
BaseExecutor template

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.

TypeHandler strategy
TypeHandler strategy

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.

PropertyTokenizer iterator
PropertyTokenizer iterator

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.

design-patternsJavaarchitectureMyBatisORM
Top Architect
Written by

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.

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.