MyBatis 使用手册:从入门到精通的全流程指南
2025.09.17 10:31浏览量:1简介:本文详细介绍了MyBatis框架的核心特性、配置方法、动态SQL、缓存机制及高级应用场景,通过代码示例和最佳实践帮助开发者快速掌握ORM工具的高效使用技巧。
MyBatis 使用手册:从入门到精通的全流程指南
一、MyBatis 核心特性与优势
MyBatis 作为一款轻量级持久层框架,通过 XML/注解配置实现 SQL 与 Java 代码的解耦,其核心优势体现在三方面:
- SQL 灵活性:开发者可直接编写原生 SQL,精准控制数据库操作,尤其适合复杂查询场景。
- 结果集映射:支持对象关系映射(ORM),将查询结果自动映射为 Java 对象,减少样板代码。
- 插件机制:通过拦截器扩展框架功能,例如分页插件、性能监控等。
典型应用场景包括:需要高频操作数据库的电商系统、对 SQL 性能敏感的金融系统,以及遗留系统改造项目。
二、环境配置与快速入门
2.1 依赖管理
Maven 项目需引入核心依赖:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
2.2 基础配置
创建 mybatis-config.xml
配置文件:
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/example/mapper/UserMapper.xml"/>
</mappers>
</configuration>
2.3 快速示例
创建实体类:
public class User {
private Long id;
private String name;
// 省略getter/setter
}
定义 Mapper 接口:
public interface UserMapper {
User selectUserById(Long id);
}
编写 XML 映射文件:
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectUserById" resultType="com.example.entity.User">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>
执行查询:
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectUserById(1L);
System.out.println(user);
}
三、核心功能深度解析
3.1 动态 SQL 实现
MyBatis 提供 <if>
、<choose>
、<foreach>
等标签实现条件拼接:
<select id="findActiveUsers" resultType="User">
SELECT * FROM user
WHERE 1=1
<if test="name != null">
AND name LIKE #{name}
</if>
<choose>
<when test="status == 'ACTIVE'">
AND status = 1
</when>
<otherwise>
AND status = 0
</otherwise>
</choose>
<foreach item="role" collection="roles" open="AND id IN (" separator="," close=")">
#{role.id}
</foreach>
</select>
3.2 关联查询处理
一对一关联
<resultMap id="userWithOrderMap" type="User">
<id property="id" column="user_id"/>
<association property="order" javaType="Order">
<id property="id" column="order_id"/>
<result property="amount" column="amount"/>
</association>
</resultMap>
<select id="getUserWithOrder" resultMap="userWithOrderMap">
SELECT u.*, o.id as order_id, o.amount
FROM user u LEFT JOIN orders o ON u.id = o.user_id
WHERE u.id = #{id}
</select>
一对多关联
<resultMap id="userWithOrdersMap" type="User">
<id property="id" column="id"/>
<collection property="orders" ofType="Order">
<id property="id" column="order_id"/>
<result property="amount" column="amount"/>
</collection>
</resultMap>
<select id="getUserWithOrders" resultMap="userWithOrdersMap">
SELECT u.*, o.id as order_id, o.amount
FROM user u LEFT JOIN orders o ON u.id = o.user_id
WHERE u.id = #{id}
</select>
3.3 缓存机制优化
一级缓存
SqlSession 级别缓存,默认开启。相同 SqlSession 执行相同查询时,直接从缓存获取结果。
二级缓存
Mapper 级别缓存,需在映射文件中配置:
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
使用注意事项:
- 实体类需实现
Serializable
接口 - 操作数据库后需调用
sqlSession.commit()
更新缓存 - 分布式环境下需结合 Redis 等外部缓存
四、高级特性实践
4.1 类型处理器
自定义枚举类型处理器示例:
public class EnumTypeHandler<E extends Enum<E>> implements TypeHandler<E> {
private Class<E> type;
public EnumTypeHandler(Class<E> type) {
this.type = type;
}
@Override
public void setParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, parameter.name());
}
@Override
public E getResult(ResultSet rs, String columnName) throws SQLException {
String value = rs.getString(columnName);
return value == null ? null : Enum.valueOf(type, value);
}
// 其他方法实现...
}
配置使用:
<typeHandlers>
<typeHandler handler="com.example.handler.EnumTypeHandler" javaType="com.example.enums.StatusEnum"/>
</typeHandlers>
4.2 插件开发
实现分页插件示例:
@Intercepts({
@Signature(type= Executor.class, method="query",
args={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
})
public class PaginationInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
RowBounds rowBounds = (RowBounds) args[2];
if (rowBounds != RowBounds.DEFAULT) {
// 实现分页逻辑
MappedStatement ms = (MappedStatement) args[0];
// 修改SQL添加LIMIT子句
}
return invocation.proceed();
}
// 其他方法实现...
}
注册插件:
<plugins>
<plugin interceptor="com.example.plugin.PaginationInterceptor"/>
</plugins>
五、最佳实践与性能优化
SQL 优化:
- 避免
SELECT *
,明确指定字段 - 复杂查询拆分为多个简单语句
- 合理使用索引
- 避免
批量操作:
try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
UserMapper mapper = session.getMapper(UserMapper.class);
for (int i = 0; i < 1000; i++) {
mapper.insertUser(new User(...));
}
session.commit();
}
连接池配置:
<dataSource type="POOLED">
<property name="poolMaximumActiveConnections" value="20"/>
<property name="poolMaximumIdleConnections" value="5"/>
<property name="poolMaximumCheckoutTime" value="20000"/>
</dataSource>
日志配置:
在log4j.properties
中添加:log4j.logger.org.mybatis=DEBUG
六、常见问题解决方案
结果集映射错误:
- 检查
resultType
/resultMap
配置 - 确保字段名与属性名匹配(或通过
@Result
注解指定)
- 检查
N+1 查询问题:
- 使用
<collection>
的fetchType="lazy"
延迟加载 - 优先考虑 JOIN 查询替代多次单表查询
- 使用
事务失效:
- 确保操作在同一个 SqlSession 中
- 显式调用
commit()
或设置自动提交
七、进阶学习资源
- 官方文档:https://mybatis.org/mybatis-3/
- GitHub 示例项目:https://github.com/mybatis/mybatis-3-examples
- 推荐书籍:《MyBatis 技术内幕》
本手册涵盖了 MyBatis 的核心功能与实战技巧,通过系统学习可显著提升数据库操作效率。建议开发者结合实际项目进行练习,逐步掌握框架的高级特性。
发表评论
登录后可评论,请前往 登录 或 注册