Understanding MyBatis SQL Execution Process and Custom TypeHandler Implementation
This article explains how MyBatis binds mapper interfaces to XML files, details the step‑by‑step SQL execution flow—including mapper retrieval, statement lookup, parameter handling, and result set mapping—and demonstrates how to create custom TypeHandler classes for both parameter setting and result extraction.
Introduction
MyBatis is a popular persistence framework, but many developers are unclear about its internal SQL execution workflow. This article walks through the complete process, covering mapper binding, SQL execution, parameter mapping, and custom TypeHandler creation.
Mapper Interface Binding (getMapper)
The SqlSession.getMapper call triggers a series of look‑ups in the Configuration and MapperRegistry , ultimately returning a JDK dynamic proxy ( MapperProxy ) that implements the mapper interface.
SqlSession session = sqlSessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
List
userList = userMapper.listUserByUserName("孤狼1号");When Mapper Interfaces and XML Files Are Associated
During SqlSessionFactoryBuilder.build() , MyBatis parses mybatis-config.xml , loads mapper interfaces, and links them to their XML mapping files via Configuration.addMapper and MapperRegistry.addMapper . This populates the knownMappers map for later retrieval.
SQL Execution Process
The execution consists of two main phases: locating the SQL statement and executing it. The proxy’s invoke method creates a MapperMethod object that holds method metadata and the associated SQL.
Locating SQL
The proxy checks the statement cache, resolves the fully‑qualified statement ID, and retrieves the MappedStatement from the configuration.
Executing SQL
Depending on the return type, MyBatis calls executeForMany (for collections) or other execution paths, eventually delegating to PreparedStatementHandler.query , which creates a PreparedStatement , sets parameters, and runs execute .
Parameter Mapping
Parameter values are set via StatementHandler.parameterize , which uses the appropriate TypeHandler (e.g., StringTypeHandler ) to call the correct JDBC setter method.
select user_id,user_name from lw_user where user_name=#{userName}Custom TypeHandler s can be specified to override the default behavior.
Custom TypeHandler Example
package com.lonelyWolf.mybatis.typeHandler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.*;
public class MyTypeHandler extends BaseTypeHandler
{
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
System.out.println("自定义typeHandler生效了");
ps.setString(i, parameter);
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
System.out.println("根据columnName获取结果->自定义typeHandler生效了");
return rs.getString(columnName);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
System.out.println("根据columnIndex获取结果->自定义typeHandler生效了");
return rs.getString(columnIndex);
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return cs.getString(columnIndex);
}
}Using the custom handler in a mapper XML:
<resultMap id="MyUserResultMap" type="lwUser">
<result column="user_id" property="userId" jdbcType="VARCHAR" typeHandler="com.lonelyWolf.mybatis.typeHandler.MyTypeHandler"/>
<result column="user_name" property="userName" jdbcType="VARCHAR"/>
</resultMap>
<select id="listUserByUserName" parameterType="String" resultMap="MyUserResultMap">
select user_id,user_name from lw_user where user_name=#{userName,jdbcType=VARCHAR,typeHandler=com.lonelyWolf.mybatis.typeHandler.MyTypeHandler}
</select>Result Set Mapping
After the JDBC query returns a ResultSet , MyBatis invokes the ResultSetHandler.handleResultSets method, which iterates over rows and uses the configured TypeHandler s to convert column values into Java objects.
Workflow Diagram
A high‑level diagram (omitted here) shows the interaction between SqlSession , Executor , StatementHandler , ResultSetHandler , and the four core MyBatis components that can be intercepted for advanced extensions.
Conclusion
The article covered (1) how mapper interfaces bind to XML files, (2) the full MyBatis SQL execution flow, (3) creating custom parameter TypeHandler s, and (4) custom result‑set TypeHandler s, providing a solid foundation for deeper source‑code exploration.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
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.