You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Spring JdbcTemplate批量更新实现插入时覆写重复记录?

嘿,你现在要实现的是批量「存在则更新、不存在则插入」(也就是开发里常说的Upsert),但你当前用的insert ignore只能跳过重复记录,没法自动更新,得调整SQL和代码逻辑才行。下面分不同数据库给你具体的实现方案:

一、MySQL数据库(最常用场景)

MySQL支持INSERT ... ON DUPLICATE KEY UPDATE语法,前提是你要在判断重复的字段(比如你代码里的aa)上建立主键或唯一索引,这样数据库才能检测到重复记录。

代码示例

// 核心SQL:aa字段必须是主键或唯一索引
String upsertSql = "INSERT INTO xxx (yy, zz, aa) VALUES (?, ?, ?) " +
                   "ON DUPLICATE KEY UPDATE yy = VALUES(yy), zz = VALUES(zz)";

int[] result = jdbcTemplate.batchUpdate(upsertSql, new BatchPreparedStatementSetter() {
    @Override
    public void setValues(PreparedStatement ps, int i) throws SQLException {
        // 按你的数据源逻辑取值,这里假设jsonArray是你的批量数据集合
        JSONObject item = new JSONObject(jsonArray.get(i).toString());
        ps.setDouble(1, item.getDouble("yy"));
        ps.setDouble(2, item.getDouble("zz"));
        ps.setString(3, item.getString("aa")); // 唯一键字段,用来判断重复
    }

    @Override
    public int getBatchSize() {
        return jsonArray.size(); // 返回批量处理的总条数
    }
});

结果说明

返回的result数组中,每个元素对应批次里单条记录的影响行数:

  • 1:表示这条记录是新插入的
  • 2:表示这条记录是已存在的,执行了更新操作
  • 0:表示记录已存在,但新旧值完全一致,没有执行更新
二、PostgreSQL数据库

PostgreSQL用ON CONFLICT ... DO UPDATE语法,同样需要先给重复判断字段建立唯一约束。

代码示例

String upsertSql = "INSERT INTO xxx (yy, zz, aa) VALUES (?, ?, ?) " +
                   "ON CONFLICT (aa) DO UPDATE SET yy = EXCLUDED.yy, zz = EXCLUDED.zz";

int[] result = jdbcTemplate.batchUpdate(upsertSql, new BatchPreparedStatementSetter() {
    @Override
    public void setValues(PreparedStatement ps, int i) throws SQLException {
        JSONObject item = new JSONObject(jsonArray.get(i).toString());
        ps.setDouble(1, item.getDouble("yy"));
        ps.setDouble(2, item.getDouble("zz"));
        ps.setString(3, item.getString("aa"));
    }

    @Override
    public int getBatchSize() {
        return jsonArray.size();
    }
});

说明

EXCLUDED代表原本要插入的那条记录,用它的字段值来覆盖现有记录的对应字段。

三、Oracle数据库

Oracle用MERGE INTO语法,写法相对复杂一点:

代码示例

String upsertSql = "MERGE INTO xxx t " +
                   "USING DUAL ON (t.aa = ?) " +
                   "WHEN MATCHED THEN UPDATE SET t.yy = ?, t.zz = ? " +
                   "WHEN NOT MATCHED THEN INSERT (yy, zz, aa) VALUES (?, ?, ?)";

int[] result = jdbcTemplate.batchUpdate(upsertSql, new BatchPreparedStatementSetter() {
    @Override
    public void setValues(PreparedStatement ps, int i) throws SQLException {
        JSONObject item = new JSONObject(jsonArray.get(i).toString());
        String aa = item.getString("aa");
        double yy = item.getDouble("yy");
        double zz = item.getDouble("zz");
        
        // 填充ON条件的参数
        ps.setString(1, aa);
        // 填充更新语句的参数
        ps.setDouble(2, yy);
        ps.setDouble(3, zz);
        // 填充插入语句的参数
        ps.setDouble(4, yy);
        ps.setDouble(5, zz);
        ps.setString(6, aa);
    }

    @Override
    public int getBatchSize() {
        return jsonArray.size();
    }
});
关键注意事项
  • 必须先建唯一约束:不管哪种数据库,都要在用来判断重复的字段(比如aa)上建立主键或唯一索引,否则Upsert逻辑不会生效
  • 异常处理:实际项目里建议加上try-catch,捕获SQLException或Spring的DataAccessException,处理批量更新中可能出现的部分失败情况
  • 性能优化:批量处理的批次大小不要过大(比如每1000条一批),避免内存溢出或数据库连接超时

内容的提问来源于stack exchange,提问作者Explain Down Vote

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:26:14