SoFunction
Updated on 2025-04-04

MyBatis Parameter Mapping Mechanism Practical Record

Core Components

1. SqlSessionFactory

The entry point of MyBatis isSqlSessionFactory, it is responsible for creatingSqlSessionExample. EachSqlSessionBoth represent a session with the database, where SQL operations can be performed.

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession session = ()) {
    // Use session to perform CRUD operation}

2. SqlSession

SqlSessionProvides methods for executing statements, committing or rolling back transactions, and getting mapper instances. It is thread-insecure and should be used within the scope of the method (i.e. created and closed on each call).

UserMapper mapper = ();
User user = (100);

3. Mapper Interface

The Mapper interface defines methods for interacting with a database, which usually correspond to SQL statements. MyBatis implements these interfaces through a dynamic proxy, allowing you to call them in your code like you would call normal Java methods.

public interface UserMapper {
    @Select("SELECT * FROM users WHERE id = #{id}")
    User getUserById(@Param("id") int id);
}

Specific process of parameter processing

ParameterHandler and TypeHandler

  • ParameterHandler: As mentioned earlier, this is the core component of MyBatis handling SQL statement parameters. It sets the corresponding value based on the placeholder in the SQL statement.
  • TypeHandler: Used to convert Java types to JDBC types and vice versa. You can register a custom oneTypeHandlerto support specific data types.

Internal working principle

  • Parsing SQL statements: When MyBatis parses XML or annotation-defined SQL statements, it recognizes all#{}and${}Placeholders and record their positions.
  • Create ParameterHandler: For each SQL statement that needs to be executed, MyBatis will create aParameterHandlerExample. This example contains information on how to populate placeholders in SQL statements.
  • Set parameter valuesParameterHandlerAll placeholders are traversed and the corresponding value is set based on the passed parameter object (can be a simple type, Java Bean, Map, or collection). If the parameter is a complex type, MyBatis will recursively access its properties until a matching value is found.
  • Application TypeHandler: For each parameter value, MyBatis will find and apply the appropriate oneTypeHandlerto ensure the correct data type conversion.
  • Execute SQL: Finally, a SQL statement with the correct parameter value is sent to the database for execution.

Implementation details of parameter mapping

Single parameter

For a single parameter, MyBatis can use the parameter name or the default name directly (e.g.param1). If you want to improve the readability of your code, it is recommended to always use@ParamThe annotation clearly specifies the parameter name.

@Select("SELECT * FROM users WHERE id = #{userId}")
User getUserById(@Param("userId") int id);

Multiple parameters

When there are multiple parameters, use@ParamAnnotations are very important because they let MyBatis know the name of each parameter, thus referring them by name in SQL. In the version of springBoot/using mybatis alone (using the @Param annotation to specify the parameter name in the SQL statement), because at compile time, the generated bytecode file will not retain the formal parameter name of the method in the Mapper interface, but use formal parameter names such as var1, var2, and.... When obtaining the parameter value, you must use the @Param annotation to specify the parameter name in the SQL statement.

@Select("SELECT * FROM orders WHERE user_id = #{userId} AND status = #{status}")
List<Order> findOrdersByUserIdAndStatus(@Param("userId") int userId, @Param("status") String status);

Java Bean or Map Parameters

For complex parameter types, such as Java Beans or Map, MyBatis automatically parses the object's properties or Map's key-value pairs, allowing you to directly reference these values ​​in SQL via attribute names or key names.

@Select("SELECT * FROM products WHERE category = #{category} AND price < #{maxPrice}")
List<Product> findProducts(ProductCriteria criteria);

Array and collection parameters

Array and collection types parameters can be passed<foreach>Tags are used to handle, which allows you to iterate over the collection and insert multi-valued conditions into SQL.

<select  resultType="Category">
  SELECT * FROM categories
  WHERE id IN
  <foreach item="id" collection="ids" open="(" separator="," close=")">
    #{id}
  </foreach>
</select>

Dynamic SQL

MyBatis supports dynamic SQL, allowing SQL statements to be constructed based on runtime conditions. This includes using<if>, <choose>, <when>, <otherwise>, <trim>, <where>, <set>, and<foreach>Label.

<select  resultType="Blog">
  SELECT * FROM BLOG
  WHERE state = 'ACTIVE'
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

Advanced Features

Custom TypeHandler

Sometimes you need to customize the conversion logic between data types. For example, deal with enum types or custom date formats. You can achieveTypeHandlerInterface and register in MyBatis to accomplish this requirement.

public class EnumTypeHandler<E extends Enum<E>> implements TypeHandler<E> {
    private final Class<E> type;
    public EnumTypeHandler(Class<E> type) {
        if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
         = type;
    }
    @Override
    public void setParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null) {
            (i, );
        } else {
            (i, ());
        }
    }
    @Override
    public E getResult(ResultSet rs, String columnName) throws SQLException {
        return (columnName) == null ? null : (type, (columnName));
    }
    @Override
    public E getResult(ResultSet rs, int columnIndex) throws SQLException {
        return (columnIndex) == null ? null : (type, (columnIndex));
    }
    @Override
    public E getResult(CallableStatement cs, int columnIndex) throws SQLException {
        return (columnIndex) == null ? null : (type, (columnIndex));
    }
}

Then register this in the MyBatis configuration fileTypeHandler

<typeHandlers>
  <typeHandler javaType="" handler=""/>
</typeHandlers>

Plug-in mechanism

MyBatis also provides a plug-in mechanism that allows developers to intercept and modify MyBatis' internal behavior, such as intercepting SQL execution, result mapping, etc. This is very useful for performance monitoring, logging and other functions.

@Intercepts({@Signature(type= , method = "update", args = {, })})
public class ExamplePlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // Add your logic here        return ();
    }
    @Override
    public Object plugin(Object target) {
        return (target, this);
    }
    @Override
    public void setProperties(Properties properties) {
        // Set plugin properties    }
}

Performance optimization and best practices

1. Batch operation

For large-scale data operations, consider using batch inserts, updates, or deletion to reduce the number of database interactions. Available<foreach>Tags combined with batch processing function.

<insert >
  INSERT INTO users (name, email)
  VALUES
  <foreach collection="list" item="user" separator=",">
    (#{}, #{})
  </foreach>
</insert>

2. Cache Policy

Rationally configure the first-level cache and the second-level cache to avoid unnecessary duplicate queries. Level 1 cache is based onSqlSession, while the secondary cache can be in multipleSqlSessionShare between.

&lt;mapper namespace=""&gt;
  &lt;cache/&gt;
  &lt;!-- Other mapping statements --&gt;
&lt;/mapper&gt;

3. Reduce unnecessary parameter passing

Pass only the necessary parameters to reduce memory consumption and improve performance. For complex objects, try to pass only the required fields.

4. Documentation and consistency

Keeping the code style consistent and adding appropriate documentation for interfaces and methods can help team collaboration and maintenance.

Error handling and debugging

1. SQL log output

Turning on SQL log output can help you debug and optimize SQL statements. MyBatis supports a variety of log frameworks, such as Log4j, SLF4J, etc.

# 
=DEBUG
=DEBUG
=DEBUG
=DEBUG

2. Exception handling

Make sure to provide sufficient information when catching exceptions to quickly locate the problem. Exceptions can be caught manually using AOP or logged in detail.

try {
    // Database operation} catch (PersistenceException e) {
    ("Database operation failed", e);
    throw e;
}

This is the end of this article about the MyBatis parameter mapping mechanism. For more related contents of MyBatis parameter mapping, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!