Master MyBatis: Core Concepts, Benefits, and Practical Tips for Java Developers
This comprehensive guide explains what MyBatis is, its advantages and drawbacks, usage scenarios, differences from Hibernate, key syntax like #{ } vs ${ }, mapping techniques, pagination, caching, lazy loading, batch operations, dynamic SQL, and how to configure mappers and plugins in Java projects.
1. What is MyBatis?
MyBatis is a semi‑ORM framework that wraps JDBC, allowing developers to focus on writing raw SQL without handling driver loading, connection creation, or statement management, thus offering high performance control and flexibility.
It supports XML or annotation configuration to map POJOs to database records, eliminating most JDBC boilerplate code.
By configuring statements via XML or annotations and mapping Java objects to dynamic SQL parameters, MyBatis generates the final SQL, executes it, and maps the result back to Java objects.
2. Advantages of MyBatis
SQL‑centric programming keeps applications and databases loosely coupled; SQL stored in XML enables centralized management and dynamic SQL generation.
Reduces over 50% of code compared with plain JDBC and removes manual connection handling.
Compatible with any JDBC‑supported database.
Integrates smoothly with Spring.
Provides mapping tags for object‑relational field mapping.
3. Disadvantages of MyBatis
Writing SQL can be labor‑intensive, especially for tables with many columns or complex joins, requiring strong SQL skills.
SQL is database‑specific, making migration difficult.
4. Suitable Scenarios
MyBatis is ideal for DAO‑layer solutions where SQL control is critical, such as high‑performance or frequently changing internet projects.
5. MyBatis vs. Hibernate
MyBatis is not a full ORM; developers write SQL manually, offering precise performance control, whereas Hibernate provides automatic ORM with database‑agnostic mapping.
6. Difference between #{} and ${}
#{}uses prepared‑statement placeholders ("?") and prevents SQL injection; ${} performs direct string replacement, which can be unsafe.
7. Handling Mismatched Column and Property Names
Method 1: Use column aliases in SQL to match POJO property names.
<select id="selectorder" parameterType="int" resultType="me.gacl.domain.order">
select order_id id, order_no orderno, order_price price
from orders
where order_id=#{id};
</select>Method 2: Define a <resultMap> that maps each column to its corresponding property.
<select id="getOrder" parameterType="int" resultMap="orderresultmap">
select * from orders where order_id=#{id}
</select>
<resultMap type="me.gacl.domain.order" id="orderresultmap">
<id property="id" column="order_id"/>
<result property="orderno" column="order_no"/>
<result property="price" column="order_price"/>
</resultMap>8. Fuzzy Query (LIKE) Example
Approach 1 – add wildcards in Java code:
String wildcardName = "%smi%";
List<Name> names = mapper.selectLike(wildcardName);
<select id="selectLike" resultType="Name">
select * from foo where bar like #{value}
</select>Approach 2 – concatenate wildcards in SQL (prone to injection):
String name = "smi";
List<Name> names = mapper.selectLike(name);
<select id="selectLike" resultType="Name">
select * from foo where bar like "%"#{value}"%"
</select>9. How Mapper Interfaces Work
The fully‑qualified interface name becomes the XML namespace; each method name matches a statement id. MyBatis creates a JDK dynamic proxy for the interface; invoking a method looks up the corresponding MapperStatement and executes the associated SQL.
10. Pagination
MyBatis provides RowBounds for in‑memory pagination and supports physical pagination via custom plugins that intercept SQL and inject dialect‑specific LIMIT/OFFSET clauses.
11. Result Mapping Forms
Using <resultMap> to explicitly map columns to properties.
Using column aliases that match property names.
12. Batch Insert
<insert id="insertName">
insert into names (name) values (#{value})
</insert>Java example:
List<String> names = Arrays.asList("fred", "barney", "betty", "wilma");
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
NameMapper mapper = sqlSession.getMapper(NameMapper.class);
for (String name : names) {
mapper.insertName(name);
}
sqlSession.commit();
} catch (Exception e) {
sqlSession.rollback();
throw e;
} finally {
sqlSession.close();
}13. Retrieving Auto‑Generated Keys
Set useGeneratedKeys="true" and specify keyProperty in the <insert> tag; MyBatis will populate the generated key into the parameter object after execution.
<insert id="insertName" useGeneratedKeys="true" keyProperty="id">
insert into names (name) values (#{name})
</insert>14. Passing Multiple Parameters
Three common ways:
Positional parameters: #{0}, #{1} in XML.
Using @Param annotations to name parameters.
Encapsulating parameters in a Map or a custom object.
15. Dynamic SQL
MyBatis supports nine dynamic tags ( trim, where, set, foreach, if, choose, when, otherwise, bind) that allow conditional SQL construction based on runtime expressions.
16. Additional XML Tags
Beyond CRUD tags, MyBatis provides <resultMap>, <parameterMap>, <sql>, <include>, and <selectKey> for reusable fragments and key generation.
17. Duplicate id Across Files
If a namespace is defined, identical id values are allowed; without a namespace, duplicate id values cause conflicts.
18. Why MyBatis Is a Semi‑Automatic ORM
Hibernate automates object‑relational mapping, while MyBatis requires explicit SQL for relationships, making it a semi‑automatic solution.
19. One‑to‑One and One‑to‑Many Associations
Use <association> for one‑to‑one and <collection> for one‑to‑many, either via joint queries or nested selects.
20. Implementing One‑to‑One
Joint query with <association> mapping.
Nested query where the child is fetched via a separate select attribute.
21. Implementing One‑to‑Many
Joint query with <collection> mapping.
Nested query using a separate select for the collection.
22. Lazy Loading Support
MyBatis can lazily load association and collection objects; it creates CGLIB proxies that trigger a secondary query when the lazy property is accessed.
23. First‑Level and Second‑Level Cache
First‑level cache: Session‑scoped PerpetualCache (HashMap), enabled by default.
Second‑level cache: Namespace‑scoped, configurable via <cache/> and external providers like Ehcache; cleared on C/U/D operations.
24. Interface Binding
Bind Java interfaces to SQL either with annotations (@Select, @Update, etc.) for simple statements or with XML files for complex queries.
25. Mapper Interface Requirements
Method name must match the XML statement id.
Parameter type must match parameterType in XML.
Return type must match resultType or resultMap.
XML namespace must be the fully‑qualified interface name.
26. Ways to Write Mappers
Extend SqlSessionDaoSupport and configure mapper XML in sqlMapConfig.xml.
Use MapperFactoryBean to create mapper proxies.
Enable mapper scanning with MapperScannerConfigurer so Spring automatically registers mapper interfaces.
27. Plugin Mechanism
MyBatis allows plugins for ParameterHandler, ResultSetHandler, StatementHandler, and Executor. Implement the Interceptor interface, annotate with @Intercepts to specify target methods, and register the plugin in the 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.
Java Interview Crash Guide
Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.
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.
