MyBatis 防坑全家桶

MyBatis 防坑全家桶

MyBatis 是一个优秀的持久层框架,但不注意细节很容易踩坑。
我把开发中最常见的 15 个坑和对应的最佳实践总结成了这份防坑全家桶,照着用,持久层更稳、更安全、更高效。


坑点对照表

坑点编号

常见坑做法

正确用法

1

直接拼接 SQL 字符串防不住注入

用 #{} 占位符

2

数据库字段与 Java 属性不一致,映射失败

用 resultMap 明确映射

3

条件查询写成一堆 if-else

用 <where> + <if>

4

内存分页

PageHelper / 数据库分页

5

忘记加事务注解

@Transactional

6

N+1 查询

延迟加载 + 合理关联映射

7

枚举等特殊类型处理混乱

自定义 TypeHandler

8

缓存导致数据不一致

选择性启用缓存

9

多表关联映射混乱

用 association / collection

10

批量操作多次执行单条 SQL

用 <foreach> 一次批量

11

多个条件互斥还用多个 <if>

用 <choose>

12

手动处理 SQL 前后 AND/OR

用 <trim>

13

每次都写字段映射

开启 mapUnderscoreToCamelCase

14

SQL 重复写

<sql> 片段复用

15

SQL 出错不好查

开启 MyBatis 日志输出


详细用法示例

1. SQL 注入防护

<select id="getUser" resultType="User">
  SELECT * FROM users WHERE id = #{id}
</select>

2. 字段与属性映射

<resultMap id="userResultMap" type="User">
  <id property="userId" column="user_id"/>
  <result property="userName" column="user_name"/>
</resultMap>

3. 动态 SQL 条件查询

<select id="findUsers" resultType="User">
  SELECT * FROM users
  <where>
    <if test="name != null">AND name = #{name}</if>
    <if test="age != null">AND age = #{age}</if>
  </where>
</select>

4. 分页处理(数据库级)

PageHelper.startPage(1, 10);
List<User> users = userMapper.selectAll();
PageInfo<User> pageInfo = new PageInfo<>(users);

5. 事务管理

@Transactional
public void updateUser(User user) {
    userMapper.update(user);
    logMapper.insertLog(user.getId(), "update");
}

6. 避免 N+1 查询

<settings>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="aggressiveLazyLoading" value="false"/>
</settings>

7. 自定义类型处理器

public class MyEnumTypeHandler implements TypeHandler<MyEnum> {
    // 实现方法
}

8. 缓存合理使用

<select id="getConfig" resultType="Config" useCache="true">
  SELECT * FROM config WHERE id = #{id}
</select>

9. 多表关联映射

<resultMap id="orderResultMap" type="Order">
  <id property="id" column="order_id"/>
  <association property="user" javaType="User">
    <id property="id" column="user_id"/>
    <result property="name" column="user_name"/>
  </association>
</resultMap>

10. 批量操作

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

11. 条件分支

<choose>
  <when test="id != null">id = #{id}</when>
  <when test="name != null">name = #{name}</when>
  <otherwise>age > 18</otherwise>
</choose>

12. SQL 拼接优化

<trim prefixOverrides="AND |OR ">
  <if test="name != null">AND name = #{name}</if>
  <if test="age != null">OR age = #{age}</if>
</trim>

13. 驼峰映射

<settings>
  <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

14. SQL 片段复用

<sql id="userColumns">id, name, age, email</sql>
<select id="getUser" resultType="User">
  SELECT <include refid="userColumns"/> FROM users WHERE id = #{id}
</select>

15. 日志调试

<settings>
  <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

总结

  • 避坑第一步:尽量不用 ${}
  • 避坑第二步:全局设置和 SQL 片段多用
  • 避坑第三步:分页、批量、缓存都要有意识地优化

掌握这些,你的 MyBatis 代码不仅更安全,还更高效、更易维护


© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
三易师傅的头像 - 鹿快
评论 共2条

请登录后发表评论