Core Components
1. SqlSessionFactory
The entry point of MyBatis isSqlSessionFactory
, it is responsible for creatingSqlSession
Example. EachSqlSession
Both 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
SqlSession
Provides 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 one
TypeHandler
to 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 a
ParameterHandler
Example. This example contains information on how to populate placeholders in SQL statements. -
Set parameter values:
ParameterHandler
All 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 one
TypeHandler
to 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@Param
The 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@Param
Annotations 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 achieveTypeHandler
Interface 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 multipleSqlSession
Share between.
<mapper namespace=""> <cache/> <!-- Other mapping statements --> </mapper>
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!