Files
1818web-hoduan/docs/banner-batch-sort-bug-fix.md
2025-11-14 17:41:15 +08:00

5.8 KiB
Raw Blame History

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 = ? ; 
...

问题原因

  1. 多语句分隔: 使用分号分隔多个UPDATE语句
  2. MySQL限制: MySQL的PreparedStatement不支持多语句执行
  3. 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 - 修复 batchUpdateSortOrder SQL语法

新增文件

  • docs/banner-batch-sort-bug-fix.md - 本修复报告

🎯 修复效果

解决的问题

  1. SQL语法错误: 消除了多语句分隔导致的语法错误
  2. 执行效率: 从多次UPDATE改为单次批量UPDATE
  3. 事务安全: 确保批量操作的原子性
  4. 代码质量: 使用标准的SQL批量更新模式

🚨 注意事项

  1. 测试验证: 确保批量排序功能正常工作
  2. 性能监控: 观察批量更新的执行时间
  3. 数据一致性: 验证所有记录都正确更新

🧪 测试建议

使用测试页面验证

  1. 访问 /test_banner_admin.html
  2. 点击"获取Banner列表"加载数据
  3. 点击"测试批量排序"生成随机排序
  4. 点击"批量更新排序"执行更新
  5. 重新加载列表验证排序是否正确

命令行测试

# 测试批量排序接口
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配置生效