以下是MyBatis框架的全面解析,涵盖基础架构、动态SQL高级用法及结果映射机制,结合实践场景与源码逻辑梳理核心要点:
一、MyBatis基础架构与核心组件
1. 框架定位与核心特性
• 定位:MyBatis是一款半自动ORM框架,通过XML或注解实现SQL与Java对象的映射,避免了JDBC冗余代码(如连接管理、结果集解析)。
• 核心功能:
• 定制化SQL:支持动态拼接SQL语句,灵活适应复杂查询需求。
• 高级映射:通过ResultMap
处理嵌套对象、集合等复杂结构。
• 事务管理:提供基础事务接口,常与Spring集成实现分布式事务。
2. 核心组件与执行流程
• 关键组件:
• SqlSessionFactory:全局单例,通过SqlSessionFactoryBuilder
加载mybatis-config.xml
生成,管理数据库连接池与配置。
• SqlSession:线程非安全,封装CRUD操作,通过getMapper()
获取Mapper接口代理对象。
• MappedStatement:存储XML/注解中定义的SQL信息(参数映射、执行逻辑、结果映射)。
• 执行流程:
- 配置加载:解析XML/注解,生成
MappedStatement
缓存(含SQL语句、参数映射规则)。 - 请求处理:接收Mapper接口调用,通过动态代理定位SQL。
- SQL解析:结合OGNL表达式动态拼接SQL,生成
BoundSql
对象。 - 执行与映射:JDBC执行后,通过
ResultSetHandler
将结果集映射为Java对象。
二、动态SQL高级用法详解
1. 基础动态标签
• <if>
:条件判断,避免空值导致的无效过滤。
<select id="searchUsers" resultType="User">
SELECT * FROM user
<where>
<if test="name != null">AND name LIKE CONCAT('%', #{name}, '%')</if>
<if test="age != null">AND age = #{age}</if>
</where>
</select>
• <choose>/<when>/<otherwise>
:多条件分支逻辑,类似Java的switch-case
。
• <foreach>
:遍历集合,支持批量操作(如IN
查询、批量插入):
<insert id="batchInsert">
INSERT INTO user (name) VALUES
<foreach item="item" collection="list" separator=",">
(#{item.name})
</foreach>
</insert>
2. 语法优化标签
• <trim>
:自定义前缀/后缀,替代<where>
或<set>
。
<update id="updateUser">
UPDATE user
<trim prefix="SET" suffixOverrides=",">
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age},</if>
</trim>
WHERE id = #{id}
</update>
• <bind>
:预处理变量,解决数据库方言兼容性问题(如模糊查询):
<select id="searchByPattern">
<bind name="pattern" value="'%' + keyword + '%'"/>
SELECT * FROM table WHERE column LIKE #{pattern}
</select>
3. 高级场景与优化
• 多数据库适配:通过databaseId
按数据库类型动态切换SQL(如MySQL与Oracle分页差异)。
• 脚本标签:在注解中使用<script>
标签嵌入动态SQL:
@Update({"<script>",
"UPDATE user SET name = #{name}",
"<if test='age != null'> , age = #{age}</if>",
"WHERE id = #{id}",
"</script>"})
void updateUserDynamic(User user);
三、结果映射机制深度解析
1. 自动映射与别名机制
• 自动映射:默认按列名与属性名匹配(支持驼峰转换)。
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
• 别名配置:简化类型全路径,提升可读性。
<typeAliases>
<typeAlias type="com.example.User" alias="User"/>
</typeAliases>
2. 自定义ResultMap
• 基础映射:处理列名与属性名不一致的场景。
<resultMap id="UserMap" type="User">
<id property="id" column="user_id"/>
<result property="userName" column="name"/>
</resultMap>
• 嵌套对象:<association>
处理一对一关系(如用户-地址)。
<resultMap id="OrderMap" type="Order">
<association property="user" javaType="User">
<id property="id" column="user_id"/>
<result property="name" column="user_name"/>
</association>
</resultMap>
• 集合映射:<collection>
处理一对多关系(如用户-订单列表):
<resultMap id="UserWithOrdersMap" type="User">
<collection property="orders" ofType="Order">
<id property="orderId" column="order_id"/>
<result property="amount" column="order_amount"/>
</collection>
</resultMap>
3. 动态结果映射
• 自动映射模式:通过autoMapping
属性局部控制。
<resultMap id="PartialMap" type="User" autoMapping="true">
<id property="id" column="id"/> <!-- 显式指定主键 -->
</resultMap>
四、最佳实践与性能优化
- 动态SQL优化:避免多层嵌套
<if>
,优先使用<trim>
简化结构。 - 结果集处理:
• 延迟加载:通过lazyLoadingEnabled
配置关联对象的按需加载。
• 二级缓存:跨会话共享数据,需注意缓存一致性(推荐Redis集成)。 - 异常处理:使用
<selectKey>
处理主键回填,避免并发问题。
通过以上技术点整合,MyBatis既能简化基础CRUD操作,又能应对复杂业务场景。更多细节可参考官方文档或技术内幕解析。