MyBatis 核心标签使用场景及用法详解
- MyBatis标签使用心得:这些年我用过的那些标签
- 一、基础标签:从入门到放弃
- 二、动态SQL:从惊艳到抓狂
- 三、`<foreach>`标签:性能杀手?
- 四、`<resultMap>`:对象映射的艺术
- 五、那些不常用但好用的标签
- 六、我的MyBatis标签使用准则
MyBatis标签使用心得:这些年我用过的那些标签
最近整理项目代码,翻出了不少老旧的MyBatis映射文件。看着这些XML配置,突然想起刚工作时被MyBatis各种标签支配的恐惧。今天就跟大家聊聊这些标签的使用心得,都是血泪教训换来的经验。
一、基础标签:从入门到放弃
刚开始用MyBatis时,觉得<select>
、<insert>
这些基础标签简直太简单了。直到有一天…
<!-- 新手常见错误示例 -->
<insert id="addUser" parameterType="User">INSERT INTO user VALUES(#{id}, #{name}, #{age})
</insert>
结果上线后各种报错,原来数据库加了新字段。这才明白要显式指定列名:
<!-- 正确写法 -->
<insert id="addUser" parameterType="User">INSERT INTO user(name, age, create_time)VALUES(#{name}, #{age}, NOW())
</insert>
血泪教训:
- 永远明确指定插入列名
- 日期处理最好在SQL里完成
- 别相信"表结构不会变"这种鬼话
二、动态SQL:从惊艳到抓狂
第一次见到<if>
标签时惊为天人,再也不用写恶心的字符串拼接了!于是写出了这样的代码:
<select id="findUsers" resultType="User">SELECT * FROM user WHERE<if test="name != null">name = #{name}</if><if test="age != null">AND age = #{age}</if>
</select>
结果当name为null时,SQL直接变成SELECT * FROM user WHERE AND age=xx
,当场爆炸。
后来才知道要用<where>
标签:
<select id="findUsers" resultType="User">SELECT * FROM user<where><if test="name != null">name = #{name}</if><if test="age != null">AND age = #{age}</if></where>
</select>
实用技巧:
<where>
会自动去除开头AND/OR- 简单条件用
<if>
,复杂逻辑用<choose>
- 记得在测试用例里覆盖所有条件分支
三、<foreach>
标签:性能杀手?
做批量操作时,<foreach>
简直是救命稻草:
<insert id="batchInsert">INSERT INTO user(name, age) VALUES<foreach collection="list" item="user" separator=",">(#{user.name}, #{user.age})</foreach>
</insert>
但是有一次导入10万条数据,直接把数据库干趴了。后来学乖了,要分批处理:
// 每批1000条
int batchSize = 1000;
List<List<User>> batches = ListUtils.partition(userList, batchSize);batches.forEach(batch -> {userMapper.batchInsert(batch);
});
性能心得:
- MySQL单批建议500-2000条
- Oracle单批建议100-500条
- 记得加事务,但别太大
四、<resultMap>
:对象映射的艺术
最让我头疼的就是复杂的对象关系映射。比如用户有角色,还有订单:
<resultMap id="userDetailMap" type="User"><id property="id" column="id"/><!-- 基础字段 --><result property="name" column="name"/><!-- 一对一 --><association property="role" javaType="Role"><id property="id" column="role_id"/><result property="name" column="role_name"/></association><!-- 一对多 --><collection property="orders" ofType="Order"><id property="id" column="order_id"/><result property="amount" column="amount"/></collection>
</resultMap>
踩过的坑:
- 别忘了
<id>
标签,否则性能很差 - 列名别名要写清楚,避免冲突
- 太复杂的映射考虑拆成多个查询
五、那些不常用但好用的标签
<trim>
:当<where>
和<set>
不够灵活时使用
<update id="updateSelective">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="search"><bind name="pattern" value="'%' + keyword + '%'"/>SELECT * FROM products WHERE name LIKE #{pattern}
</select>
六、我的MyBatis标签使用准则
- KISS原则:能简单就别复杂
- 显式优于隐式:明确指定列名和映射关系
- 性能意识:注意批量操作的数据量
- 可读性:适当换行和注释
- 安全第一:永远用
#{}
,不用${}
这些年用下来,MyBatis的标签设计确实很实用。刚开始可能会觉得复杂,但熟悉后会发现它们能优雅地解决各种SQL问题。关键是要理解每个标签的设计初衷,而不是死记硬背。