如何使用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
相关产品推荐
相关产品推荐

