QueryDsl使用两个List参数完成批量更新的实现方案咨询
可行解决方案
方案1:使用QueryDSL的Case When语法拼接单次更新语句
该方案可以生成单条UPDATE语句一次提交执行,无需循环向数据库发送请求,适合单次更新条数小于1000的场景,避免SQL语句过长。
代码示例:// 先定义接收ID和对应账号的DTO类 public class EmployeeAccountDTO { private Long id; private String account; // 省略get、set方法 } // 调整后的更新方法 public void updateEmployeeData(List<EmployeeAccountDTO> employeeAccountList) { CaseBuilder.Cases<String, String> cases = new CaseBuilder.Cases<>(String.class); // 遍历拼接所有ID和账号的映射规则 for (EmployeeAccountDTO dto : employeeAccountList) { cases = cases.when(employee.employeeId.eq(dto.getId())).then(dto.getAccount()); } // 提取所有需要更新的ID集合作为过滤条件,避免全表扫描 List<Long> idList = employeeAccountList.stream() .map(EmployeeAccountDTO::getId) .toList(); queryFactory.update(employee) .set(employee.employeeAccount, cases.otherwise(employee.employeeAccount)) .where(employee.employeeId.in(idList)) .execute(); }最终生成的SQL逻辑如下:
UPDATE employee SET employee_account = CASE WHEN employee_id = 1 THEN '账号1' WHEN employee_id = 2 THEN '账号2' ... ELSE employee_account END WHERE employee_id IN (1,2,...)方案2:使用JDBC批量更新
适合更新量较大的场景,将多条更新语句攒为一批提交到数据库,减少多次网络往返的开销,性能远高于循环单条执行。
代码示例:@Autowired private JdbcTemplate jdbcTemplate; public void updateEmployeeData(List<EmployeeAccountDTO> employeeAccountList) { String updateSql = "UPDATE employee SET employee_account = ? WHERE employee_id = ?"; jdbcTemplate.batchUpdate(updateSql, new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int index) throws SQLException { EmployeeAccountDTO dto = employeeAccountList.get(index); ps.setString(1, dto.getAccount()); ps.setLong(2, dto.getId()); } @Override public int getBatchSize() { return employeeAccountList.size(); } }); }方案3:临时表关联更新
适合单次更新上万条的超大规模场景,先将ID和账号的映射写入临时表,再通过表关联完成批量更新,性能最优。
核心SQL逻辑:-- 创建临时表存储映射关系 CREATE TEMPORARY TABLE temp_account_map (employee_id BIGINT, account VARCHAR(64)); -- 批量插入映射数据 INSERT INTO temp_account_map VALUES (1,'账号1'),(2,'账号2'),(3,'账号3'),...; -- 关联执行更新 UPDATE employee e INNER JOIN temp_account_map t ON e.employee_id = t.employee_id SET e.employee_account = t.account;
内容的提问来源于stack exchange,提问作者John Hue
相关产品推荐
相关产品推荐

