Master MyBatis: Core Concepts, Best Practices, and Advanced Techniques
This comprehensive guide explains what MyBatis is, its advantages and drawbacks, suitable use cases, differences from Hibernate, parameter handling, dynamic SQL, pagination, caching, lazy loading, and how to use mapper interfaces, XML mappings, and plugins with clear code examples.
What Is MyBatis?
MyBatis is a semi‑ORM framework that wraps JDBC, allowing developers to focus on writing raw SQL while handling driver loading, connection creation, and statement management internally. It supports XML or annotation‑based configuration to map POJOs to database records.
Advantages of MyBatis
SQL‑centric programming offers high flexibility and does not impose constraints on existing database designs.
Reduces boilerplate JDBC code by more than 50%.
Works with any JDBC‑compatible database.
Integrates smoothly with Spring.
Provides mapping tags for object‑relational field mapping.
Drawbacks of MyBatis
Writing SQL can be labor‑intensive, especially for tables with many columns or complex joins, requiring solid SQL skills.
SQL is tied to a specific database, making portability between different databases difficult.
Suitable Scenarios
Projects that need fine‑grained control over SQL performance.
Applications with frequent requirement changes or high performance demands, such as internet‑scale services.
Differences Between MyBatis and Hibernate
MyBatis requires developers to write SQL manually, offering precise performance control but less database‑agnostic support.
Hibernate provides full ORM capabilities, generating SQL automatically and offering better database independence.
#{} vs ${} in MyBatis
#{}uses prepared‑statement placeholders, preventing SQL injection. ${} performs direct string substitution, which can lead to injection if not used carefully.
Handling Mismatched Field Names
Two approaches are common: define column aliases in the SQL to match POJO property names, or use a <resultMap> to map columns to properties explicitly.
Fuzzy Query (LIKE) Examples
<select id="selectLike">
SELECT * FROM foo WHERE bar LIKE #{value}
</select>Pass a wildcard string (e.g., "%smi%") as the parameter. Direct concatenation of wildcards is discouraged due to injection risk.
Mapper Interface Mechanics
The fully qualified name of a mapper interface serves as the XML namespace; each method name matches a statement id. MyBatis creates a JDK dynamic proxy for the interface, intercepts method calls, looks up the corresponding MapperStatement, executes the SQL, and returns the result. Overloading methods is not supported because the lookup key is namespace+methodName.
Pagination
MyBatis can paginate in memory using RowBounds or perform physical pagination by writing SQL with limit/offset clauses. Pagination plugins intercept the SQL, rewrite it according to the database dialect, and add appropriate pagination parameters.
Result Mapping Forms
Explicit <resultMap> tags mapping columns to properties.
Using column aliases in SQL to match POJO property names.
Batch Insert
<insert id="insertName">
INSERT INTO names (name) VALUES (#{value})
</insert>Execute batch inserts by opening a session with ExecutorType.BATCH and iterating over the data list, committing after the loop.
Retrieving Auto‑Generated Keys
<insert id="insertName" useGeneratedKeys="true" keyProperty="id">
INSERT INTO names (name) VALUES (#{name})
</insert>After execution, the generated key is populated into the parameter object's id field.
Passing Multiple Parameters
Use indexed placeholders #{0}, #{1} for positional parameters.
Annotate method parameters with @Param("name") to reference them by name.
Wrap multiple values in a Map and reference entries via #{key}.
Dynamic SQL
MyBatis supports nine dynamic tags ( trim, where, set, foreach, if, choose, when, otherwise, bind) that conditionally build SQL based on expression values.
Additional XML Tags
Beyond select, insert, update, and delete, MyBatis XML can contain <resultMap>, <parameterMap>, <sql>, <include>, and <selectKey> for advanced mapping and key generation.
Duplicate IDs Across XML Files
If an XML file defines a namespace, IDs can repeat across files because the full key is namespace+id. Without a namespace, IDs must be unique globally.
Semi‑Automatic ORM Explanation
Unlike fully automatic ORM tools like Hibernate, MyBatis requires developers to write SQL manually for queries and associations, offering more control but less automation.
One‑to‑One and One‑to‑Many Associations
<mapper namespace="com.example.UserMapper">
<!-- One‑to‑one association -->
<select id="getClass" resultMap="ClassResultMap">
SELECT * FROM class c, teacher t WHERE c.teacher_id = t.id AND c.id = #{id}
</select>
<resultMap type="Class" id="ClassResultMap">
<id property="id" column="c_id"/>
<association property="teacher" javaType="Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
</resultMap>
<!-- One‑to‑many collection -->
<select id="getClassWithStudents" resultMap="ClassWithStudents">
SELECT * FROM class c, teacher t, student s WHERE c.teacher_id = t.id AND c.id = s.class_id AND c.id = #{id}
</select>
<resultMap type="Class" id="ClassWithStudents">
<id property="id" column="c_id"/>
<association property="teacher" javaType="Teacher"> ... </association>
<collection property="students" ofType="Student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection>
</resultMap>
</mapper>Lazy Loading Support
MyBatis can lazily load association (one‑to‑one) and collection (one‑to‑many) objects by setting lazyLoadingEnabled=true. It uses CGLIB proxies to fetch related data only when accessed.
Caching
First‑level cache: Session‑scoped PerpetualCache (enabled by default).
Second‑level cache: Namespace‑scoped, configurable (e.g., Ehcache). Requires the cache class to be serializable.
Cache is cleared automatically after any insert, update, or delete operation within the same scope.
Interface Binding
Any Java interface can be bound to SQL statements. Binding can be done via annotations ( @Select, @Update, etc.) for simple statements or via XML files where the namespace matches the interface’s fully qualified name.
Mapper Usage Requirements
Method name must match the id of the corresponding SQL statement.
Method parameter types must correspond to the statement’s parameterType.
Method return type must match the statement’s resultType or resultMap.
The XML file’s namespace must be the fully qualified name of the mapper interface.
Plugin Mechanism
MyBatis allows plugins for the four core interfaces: ParameterHandler, ResultSetHandler, StatementHandler, and Executor. A plugin implements the Interceptor interface, overrides intercept(), and is registered via annotations and configuration.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
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.
