当前位置: 首页 > news >正文

MyBatis 动态 SQL 完整笔记


MyBatis 动态 SQL 完整笔记


一、核心动态 SQL 标签与用法

1. 条件控制类标签

  • <if>:基础条件判断
    示例:根据 nameage 动态筛选用户

    <if test="name != null and name != ''">AND user_name = #{name}
    </if>
    
  • <choose>/<when>/<otherwise>:多条件分支
    示例:类似 Java 的 switch-case,优先匹配首个满足条件的 <when>

    <choose><when test="type == 'admin'">AND role = 'admin'</when><otherwise>AND role = 'guest'</otherwise>
    </choose>
    

2. 语法修正类标签

  • <where>:自动处理 WHERE 关键字和首条条件前的 AND/OR

    <where><if test="age != null">AND age = #{age}</if>
    </where>
    
  • <trim>:更灵活的语法修正(替代 <where><set>
    示例:自定义前缀/后缀及需删除的字符

    <trim prefix="WHERE" prefixOverrides="AND |OR"><if test="name != null">AND name=#{name}</if>
    </trim>
    
  • <set>:自动处理 UPDATE 语句的 SET 子句
    示例:动态更新字段并去除末尾逗号

    <set><if test="name != null">name=#{name},</if><if test="age != null">age=#{age}</if>
    </set>
    

3. 集合处理类标签

  • <foreach>:遍历集合(批量操作/IN 查询)

    <foreach collection="list" item="item" open="(" separator="," close=")">#{item.id}
    </foreach>
    
  • <bind>:预定义变量(优化模糊查询等场景)

    <bind name="namePattern" value="'%' + name + '%'"/>
    WHERE username LIKE #{namePattern}
    

二、性能优化与最佳实践

1. OGNL 表达式优化

  • 避免复杂嵌套表达式,优先在 Java 层处理判断逻辑
    <if test="@com.utils.MyBatisUtils@isValid(name)">
    

2. 批量操作优化

  • 使用 BATCH 模式执行 SqlSession,减少数据库连接开销
  • 分批次处理超大数据集(如每 1000 条提交一次)

3. 缓存策略

  • 二级缓存配置(Mapper 级别,跨会话共享)
    <mapper namespace="com.UserMapper"><cache eviction="LRU" flushInterval="60000"/>
    </mapper>
    
  • 注意脏读问题:更新操作后手动清除缓存
    <update id="updateUser" flushCache="true">
    

三、高频场景实战示例

1. 动态排序与分页

<select id="selectUsers" resultMap="UserResultMap">SELECT * FROM users<where><if test="orderBy != null">ORDER BY ${orderBy} <!-- 注意 SQL 注入风险 --></if><if test="offset >=0 and limit >0">LIMIT #{offset}, #{limit}</if></where>
</select>

2. 多字段模糊查询

<bind name="searchKey" value="'%' + key + '%'"/>
<where>(title LIKE #{searchKey} OR content LIKE #{searchKey})
</where>

3. 批量插入优化

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

四、安全与规范

1. 防 SQL 注入

  • 禁止直接拼接 ${} 参数(除非绝对可信)
  • 使用 #{} 预编译参数化查询

2. 参数校验

  • 集合判空:<if test="list != null and !list.isEmpty()">
  • 字符串处理:<if test="name != null and name.trim() != ''">

3. 类型安全

  • 显式声明 jdbcType(避免 NULL 类型推断错误)
    #{age,jdbcType=INTEGER}
    

五、高级特性

1. 注解动态 SQL

@SelectProvider(type = UserSqlBuilder.class, method = "buildQuery")
List<User> findUsers(UserQuery query);

2. 动态表名映射

<select id="selectByTable" resultType="map">SELECT * FROM ${tableName}
</select>

最佳实践总结

  1. 优先使用 <where>/<set> 替代手动处理 SQL 语法
  2. 复杂条件判断应前移至 Java 代码处理
  3. 批量操作需配合数据库连接池优化
  4. 高频读场景启用二级缓存,但注意数据一致性
  5. 使用 <bind> 统一处理格式转换(如日期/模糊查询)

相关文章:

  • 世界少棒联盟(Little League Baseball)·棒球1号位
  • 【LangChain基础系列】深入全面掌握文本分类
  • C——VS的调试技巧
  • 更多 QVariant 使用案例
  • Python序列Day3
  • 如何对 Oracle 日志文件进行校验
  • 钯铂贵金属分离回收树脂
  • Nginx 配置多个监听端口
  • obj = null; 赋值null之前没有其他引用指向obj对象,那么,当obj=null时,会被垃圾回收机制立即回收吗?
  • 编程题 02-线性结构2 一元多项式的乘法与加法运算【PAT】
  • PostgreSQL 的 pg_current_logfile 函数
  • 【Ubuntu】Netplan静态网络配置
  • 缺乏实体人形机器人的主流高精度仿真方案
  • Flutter接入ProtoBuff和原生Android通信【性能最优】
  • tmux 入门与实用指南
  • 39、.NET GC是什么? 为什么需要GC?
  • 深泽多层电路在PCB行业中属于什么水平
  • 初识Linux · 传输层协议TCP · 上
  • Python爬虫中time.sleep()与动态加载的配合使用
  • C语言自定义类型:联合与枚举详解
  • 市自规局公告收回新校区建设用地,宿迁学院:需变更建设主体
  • 复旦大学文科杰出教授裘锡圭逝世,享年90岁
  • 外交部:解放军参加红场阅兵体现了中方对历史的尊重和铭记
  • 金正恩视察重要军工企业要求推进武力强化变革
  • 央行:增加支农支小再贷款额度3000亿元
  • 央行行长详解降息:将通过利率自律机制引导商业银行相应下调存款利率