Spring如何编写通用服务类返回对应表的JDBC批量更新实现类对象
可行实现方案
1. 定义核心基础组件
首先定义标识表名的注解和统一批量更新接口,规范所有更新器的实现标准:
// 表更新器标识注解,作用在实现类上指定对应的表名 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Component public @interface TableUpdater { String value(); } // 统一批量更新接口 public interface BaseBatchUpdater<T> { void updateBatch(List<T> dataList); }
2. 实现批量更新器
支持两种实现模式,满足不同表的逻辑需求:
有自定义逻辑的表单独实现
// TableA的专属批量更新器,直接加注解指定表名即可,无需修改其他业务代码 @TableUpdater("TableA") public class TableABatchUpdater implements BaseBatchUpdater<TableAEntity> { @Autowired private JdbcTemplate jdbcTemplate; @Override public void updateBatch(List<TableAEntity> dataList) { // 自定义TableA的批量更新逻辑 String sql = "update table_a set column1 = ?, column2 = ? where id = ?"; jdbcTemplate.batchUpdate(sql, dataList, dataList.size(), (ps, entity) -> { ps.setObject(1, entity.getColumn1()); ps.setObject(2, entity.getColumn2()); ps.setObject(3, entity.getId()); }); } }
无特殊逻辑的表用通用实现
无需单独写实现类,直接复用通用更新器:
public class CommonBatchUpdater<T> implements BaseBatchUpdater<T> { private final JdbcTemplate jdbcTemplate; private final String updateSql; private final Function<T, Object[]> paramMapper; public CommonBatchUpdater(JdbcTemplate jdbcTemplate, String updateSql, Function<T, Object[]> paramMapper) { this.jdbcTemplate = jdbcTemplate; this.updateSql = updateSql; this.paramMapper = paramMapper; } @Override public void updateBatch(List<T> dataList) { jdbcTemplate.batchUpdate(updateSql, dataList.stream().map(paramMapper).toList()); } }
3. 实现统一调度服务BatchUpdaterService
自动收集所有更新器实例,构建表名和更新器的映射关系:
@Service public class BatchUpdaterService { private final Map<String, BaseBatchUpdater<?>> updaterMap = new HashMap<>(); @Autowired private JdbcTemplate jdbcTemplate; // Spring自动注入所有BaseBatchUpdater的实现类 @Autowired public BatchUpdaterService(List<BaseBatchUpdater<?>> customUpdaters) { // 先注册自定义实现的更新器 customUpdaters.forEach(updater -> { TableUpdater anno = updater.getClass().getAnnotation(TableUpdater.class); if (anno != null) { updaterMap.put(anno.value(), updater); } }); // 注册通用实现的更新器,新增无特殊逻辑的表只需要在这里加一行即可 registerCommonUpdater("TableD", "update table_d set col = ? where id = ?", (TableDEntity entity) -> new Object[]{entity.getCol(), entity.getId()}); } private <T> void registerCommonUpdater(String tableName, String sql, Function<T, Object[]> paramMapper) { updaterMap.put(tableName, new CommonBatchUpdater<>(jdbcTemplate, sql, paramMapper)); } @SuppressWarnings("unchecked") public <T> BaseBatchUpdater<T> getTableUpdater(String tableName) { BaseBatchUpdater<?> updater = updaterMap.get(tableName); if (updater == null) { throw new IllegalArgumentException("未找到对应表的批量更新器: " + tableName); } return (BaseBatchUpdater<T>) updater; } }
4. 业务侧使用
和你预期的调用逻辑完全一致,后续新增表不需要修改这段代码:
@Service public class MyServiceClass { @Autowired private BatchUpdaterService batchUpdaterService; public void updateTables() { batchUpdaterService.getTableUpdater("TableA").updateBatch(tableAList); batchUpdaterService.getTableUpdater("TableB").updateBatch(tableBList); batchUpdaterService.getTableUpdater("TableC").updateBatch(tableCList); // 新增TableD直接加下面一行即可,不需要改动当前类的依赖注入 // batchUpdaterService.getTableUpdater("TableD").updateBatch(tableDList); } }
优化建议
- 可以在
getTableUpdater方法中增加实体类型校验,避免泛型强制转换的运行时异常 - 配合MyBatis-Plus等ORM框架使用的话,可以直接复用框架内置的批量更新能力,进一步简化通用实现的代码
- 可将通用更新器的配置(表名、更新SQL、参数映射规则)存入配置文件,启动时自动扫描注册,新增通用表连
BatchUpdaterService的代码都不需要修改
内容的提问来源于stack exchange,提问作者Pamuleti Pullagura
相关产品推荐
相关产品推荐

