5.8 KiB
5.8 KiB
Banner批量排序SQL语法Bug修复报告
🐛 问题描述
错误信息
SQLSyntaxErrorException: You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use near
'UPDATE banner SET sort_order = 2, update_time =' at line 6
错误位置
- 方法:
BannerMapper.batchUpdateSortOrder - 文件:
BannerMapper.xml - 操作: 批量更新Banner排序
🔍 根本原因分析
问题SQL语法
<!-- ❌ 错误的SQL语法 -->
<update id="batchUpdateSortOrder">
<foreach collection="banners" item="banner" separator=";">
UPDATE banner SET
sort_order = #{banner.sortOrder},
update_time = NOW()
WHERE id = #{banner.id}
</foreach>
</update>
生成的错误SQL
UPDATE banner SET sort_order = ?, update_time = NOW() WHERE id = ? ;
UPDATE banner SET sort_order = ?, update_time = NOW() WHERE id = ? ;
UPDATE banner SET sort_order = ?, update_time = NOW() WHERE id = ? ;
...
问题原因
- 多语句分隔: 使用分号分隔多个UPDATE语句
- MySQL限制: MySQL的PreparedStatement不支持多语句执行
- MyBatis误用:
separator=";"不适用于UPDATE操作
✅ 修复方案
新的SQL实现
<!-- ✅ 正确的SQL语法 -->
<update id="batchUpdateSortOrder">
UPDATE banner
SET sort_order = CASE
<foreach collection="banners" item="banner">
WHEN id = #{banner.id} THEN #{banner.sortOrder}
</foreach>
ELSE sort_order
END,
update_time = NOW()
WHERE id IN
<foreach collection="banners" item="banner" open="(" separator="," close=")">
#{banner.id}
</foreach>
</update>
生成的正确SQL
UPDATE banner
SET sort_order = CASE
WHEN id = 1 THEN 5
WHEN id = 2 THEN 2
WHEN id = 3 THEN 3
WHEN id = 4 THEN 4
WHEN id = 5 THEN 1
ELSE sort_order
END,
update_time = NOW()
WHERE id IN (1, 2, 3, 4, 5)
📊 修复前后对比
修复前
| 问题 | 影响 |
|---|---|
| ❌ 多语句UPDATE分隔 | 语法错误,无法执行 |
| ❌ 使用分号分隔符 | MySQL PreparedStatement不支持 |
| ❌ 执行失败 | 批量排序功能无法使用 |
修复后
| 改进 | 效果 |
|---|---|
| ✅ 单一CASE WHEN UPDATE | 标准SQL语法,完全兼容 |
| ✅ 批量条件更新 | 一次执行更新多个记录 |
| ✅ 高效执行 | 比多次单独UPDATE更快 |
🧪 测试验证
测试数据示例
// 批量排序数据
[
{"id": 1, "sortOrder": 5},
{"id": 2, "sortOrder": 2},
{"id": 3, "sortOrder": 3},
{"id": 4, "sortOrder": 4},
{"id": 5, "sortOrder": 1}
]
生成的SQL验证
UPDATE banner
SET sort_order = CASE
WHEN id = 1 THEN 5
WHEN id = 2 THEN 2
WHEN id = 3 THEN 3
WHEN id = 4 THEN 4
WHEN id = 5 THEN 1
ELSE sort_order
END,
update_time = NOW()
WHERE id IN (1, 2, 3, 4, 5)
预期结果
- ✅ SQL语法正确,可以正常执行
- ✅ 所有指定ID的记录都会更新排序值
- ✅ 未指定的记录保持原有排序值不变
- ✅ 所有记录的
update_time都会更新
🛡️ SQL最佳实践
1. 批量更新策略
-- ✅ 推荐:使用CASE WHEN进行批量更新
UPDATE table_name
SET column1 = CASE
WHEN condition1 THEN value1
WHEN condition2 THEN value2
ELSE column1
END
WHERE id IN (id_list);
-- ❌ 避免:多语句分隔
UPDATE table SET col=val WHERE id=1;
UPDATE table SET col=val WHERE id=2;
2. MyBatis批量操作
<!-- ✅ 正确的批量更新 -->
<update id="batchUpdate">
UPDATE table SET field = CASE
<foreach collection="list" item="item">
WHEN id = #{item.id} THEN #{item.value}
</foreach>
ELSE field
END
WHERE id IN
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item.id}
</foreach>
</update>
<!-- ❌ 错误的多语句方式 -->
<update id="batchUpdateWrong">
<foreach collection="list" item="item" separator=";">
UPDATE table SET field = #{item.value} WHERE id = #{item.id}
</foreach>
</update>
3. 性能优势
| 方式 | SQL语句数 | 网络往返 | 事务处理 |
|---|---|---|---|
| CASE WHEN批量 | 1条 | 1次 | 原子操作 |
| 多次单独UPDATE | N条 | N次 | 需要显式事务 |
📋 文件变更清单
修改文件
- ✅
src/main/resources/mapper/BannerMapper.xml- 修复batchUpdateSortOrderSQL语法
新增文件
- ✅
docs/banner-batch-sort-bug-fix.md- 本修复报告
🎯 修复效果
✅ 解决的问题
- SQL语法错误: 消除了多语句分隔导致的语法错误
- 执行效率: 从多次UPDATE改为单次批量UPDATE
- 事务安全: 确保批量操作的原子性
- 代码质量: 使用标准的SQL批量更新模式
🚨 注意事项
- 测试验证: 确保批量排序功能正常工作
- 性能监控: 观察批量更新的执行时间
- 数据一致性: 验证所有记录都正确更新
🧪 测试建议
使用测试页面验证
- 访问
/test_banner_admin.html - 点击"获取Banner列表"加载数据
- 点击"测试批量排序"生成随机排序
- 点击"批量更新排序"执行更新
- 重新加载列表验证排序是否正确
命令行测试
# 测试批量排序接口
curl -X PUT "http://localhost:8081/admin/banners/batch-sort" \
-H "Authorization: Bearer {admin_token}" \
-H "Content-Type: application/json" \
-d '[{"id":1,"sortOrder":5},{"id":2,"sortOrder":2}]'
修复状态: ✅ 已完成
测试状态: ⏳ 待验证
风险等级: 低(只影响批量排序功能)
部署要求: 重启服务器使MyBatis配置生效