Spring Boot + MyBatis 动态字段更新方法

在Spring Boot和MyBatis中,实现动态更新不固定字段的步骤如下:

方法一:使用MyBatis动态SQL(适合字段允许为null的场景)

  1. 定义实体类

    包含所有可能被更新的字段。

  2. Mapper接口

    定义更新方法,参数为实体对象:

    java

    复制代码
    void updateUserSelective(User user);
  3. XML映射文件

    使用<set><if>动态生成SQL:

    xml

    复制代码
    <update id="updateUserSelective" parameterType="User">
        UPDATE user
        <set>
            <if test="name != null">name = #{name},</if>
            <if test="age != null">age = #{age},</if>
            <if test="address != null">address = #{address},</if>
            <if test="phone != null">phone = #{phone},</if>
        </set>
        WHERE id = #{id}
    </update>

注意 :此方法无法将字段更新为null,因为参数为null时条件不成立。


方法二:使用Map和字段过滤(支持字段更新为null)

  1. Service层过滤字段

    在Service中定义允许更新的字段,并过滤请求参数:

    java

    复制代码
    public void updateUser(Long id, Map<String, Object> updates) {
        Set<String> allowedFields = Set.of("name", "age", "address", "phone");
        updates.keySet().retainAll(allowedFields); // 过滤非法字段
        userMapper.updateUserSelective(id, updates);
    }
  2. Mapper接口

    使用Map接收动态字段:

    java

    复制代码
    void updateUserSelective(@Param("id") Long id, @Param("updates") Map<String, Object> updates);
  3. XML映射文件

    动态生成更新语句:

    xml

    复制代码
    <update id="updateUserSelective">
        UPDATE user
        <set>
            <foreach collection="updates" index="key" item="value" separator=",">
                ${key} = #{value}
            </foreach>
        </set>
        WHERE id = #{id}
    </update>

注意 :使用${key}存在SQL注入风险,需在Service层严格过滤字段名。


方法三:使用@UpdateProvider(灵活且安全)

  1. 定义SQL提供类

    动态构建安全SQL:

    java

    复制代码
    public class UserSqlProvider {
        public String updateSelective(Map<String, Object> params) {
            Long id = (Long) params.get("id");
            Map<String, Object> updates = (Map<String, Object>) params.get("updates");
            Set<String> allowedFields = Set.of("name", "age", "address", "phone");
            
            StringBuilder sql = new StringBuilder("UPDATE user SET ");
            allowedFields.forEach(field -> {
                if (updates.containsKey(field)) {
                    sql.append(field).append(" = #{updates.").append(field).append("}, ");
                }
            });
            sql.setLength(sql.length() - 2); // 移除末尾逗号
            sql.append(" WHERE id = #{id}");
            return sql.toString();
        }
    }
  2. Mapper接口

    使用@UpdateProvider注解:

    java

    复制代码
    @UpdateProvider(type = UserSqlProvider.class, method = "updateSelective")
    void updateUserSelective(@Param("id") Long id, @Param("updates") Map<String, Object> updates);

优点:避免SQL注入,动态生成安全语句。


总结

  • 方法一 适合简单场景,字段无需设置为null

  • 方法二灵活,需严格过滤字段。

  • 方法三推荐用于生产环境,安全且维护性强。

根据需求选择合适方案,确保字段更新的灵活性和安全性。

相关推荐
C雨后彩虹17 小时前
计算疫情扩散时间
java·数据结构·算法·华为·面试
2601_9498095917 小时前
flutter_for_openharmony家庭相册app实战+我的Tab实现
java·javascript·flutter
vx_BS8133018 小时前
【直接可用源码免费送】计算机毕业设计精选项目03574基于Python的网上商城管理系统设计与实现:Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制
java·python·课程设计
2601_9498683618 小时前
Flutter for OpenHarmony 电子合同签署App实战 - 已签合同实现
java·开发语言·flutter
达文汐18 小时前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
培风图南以星河揽胜18 小时前
Java版LeetCode热题100之零钱兑换:动态规划经典问题深度解析
java·leetcode·动态规划
启山智软19 小时前
【中大企业选择源码部署商城系统】
java·spring·商城开发
我真的是大笨蛋19 小时前
深度解析InnoDB如何保障Buffer与磁盘数据一致性
java·数据库·sql·mysql·性能优化
奋进的芋圆19 小时前
Spring Boot 实现三模安全登录:微信扫码 + 手机号验证码 + 邮箱验证码
spring boot·redis·微信
怪兽源码19 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统