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

如何通过Spring JdbcTemplate batchUpdate获取批量插入的行数据

JdbcTemplate批量插入Oracle后获取插入数据的方案

针对Spring Boot 2.7.12 + ojdbc8 + Oracle的环境,在JdbcTemplate批量插入无法使用KeyHolder的情况下,可通过以下几种方式取回插入的行数据:

1. 预生成主键(利用Oracle序列)

Oracle的序列可以提前批量生成主键值,将这些主键与业务数据一起插入,插入完成后直接持有主键,无需额外查询:

// 批量获取序列值
List<Long> ids = jdbcTemplate.queryForList(
    "SELECT YOUR_SEQ.NEXTVAL FROM DUAL CONNECT BY LEVEL <= ?",
    new Object[]{batchSize},
    Long.class
);

// 组装插入数据,将预生成的ID与业务字段绑定
List<Object[]> batchArgs = new ArrayList<>();
for (int i = 0; i < dataList.size(); i++) {
    YourEntity entity = dataList.get(i);
    batchArgs.add(new Object[]{ids.get(i), entity.getField1(), entity.getField2()});
}

// 执行批量插入
jdbcTemplate.batchUpdate(
    "INSERT INTO YOUR_TABLE(ID, FIELD1, FIELD2) VALUES (?, ?, ?)",
    batchArgs
);

// 此时ids列表就是插入行的主键,可直接关联业务数据

2. 通过唯一业务字段批量查询

如果插入的数据包含唯一业务标识(比如唯一编码、手机号等),插入完成后可通过这些标识批量查询插入的行:

// 先执行批量插入
jdbcTemplate.batchUpdate(
    "INSERT INTO YOUR_TABLE(FIELD1, FIELD2) VALUES (?, ?)",
    dataList.stream().map(entity -> new Object[]{entity.getField1(), entity.getField2()}).collect(Collectors.toList())
);

// 提取唯一业务字段,构造IN查询
List<String> uniqueFields = dataList.stream().map(YourEntity::getUniqueField).collect(Collectors.toList());
String inClause = String.join(",", Collections.nCopies(uniqueFields.size(), "?"));

// 查询插入的行数据
List<YourEntity> insertedEntities = jdbcTemplate.query(
    String.format("SELECT ID, FIELD1, FIELD2 FROM YOUR_TABLE WHERE UNIQUE_FIELD IN (%s)", inClause),
    uniqueFields.toArray(),
    (rs, rowNum) -> {
        YourEntity entity = new YourEntity();
        entity.setId(rs.getLong("ID"));
        entity.setField1(rs.getString("FIELD1"));
        entity.setField2(rs.getString("FIELD2"));
        return entity;
    }
);

注意:必须确保业务字段的唯一性,否则会查询到无关数据

3. 使用Oracle RETURNING子句批量获取结果

ojdbc8支持Oracle的RETURNING子句,可在批量插入时直接返回指定字段(比如主键),结合CallableStatement实现:

String sql = "INSERT INTO YOUR_TABLE(FIELD1, FIELD2) VALUES (?, ?) RETURNING ID INTO ?";

jdbcTemplate.execute((Connection conn) -> {
    try (CallableStatement cs = conn.prepareCall(sql)) {
        // 注册输出参数,用于接收返回的主键
        cs.registerOutParameter(3, Types.BIGINT);
        
        for (YourEntity entity : dataList) {
            cs.setString(1, entity.getField1());
            cs.setString(2, entity.getField2());
            cs.addBatch();
        }
        
        // 执行批量插入
        cs.executeBatch();
        
        // 提取返回的主键
        List<Long> insertedIds = new ArrayList<>();
        for (int i = 0; i < dataList.size(); i++) {
            insertedIds.add(cs.getLong(3));
            // 重置输出参数,处理下一条
            cs.clearParameters();
        }
        
        // 可根据主键查询完整行数据,或直接关联业务数据
        return insertedIds;
    }
});

内容的提问来源于stack exchange,提问作者timgallin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:34:56