如何在Spring Batch处理器中执行查询实现字段校验,附现有配置代码
Spring Batch处理器内执行查询做字段校验的实现方案
你可以直接在现有处理器的基础上做如下改造,无需调整其他已定义的Reader、Writer、Step逻辑:
实现步骤
- 第一步:给处理器注入查询依赖
你已经将CaricoDTOItemProcessorStep1声明为Spring管理的Bean,直接在类中注入所需的数据库操作组件即可,推荐直接注入JdbcTemplate,也可以注入你自行封装的DAO、Mapper、Repository等持久层组件。改造后的处理器类示例如下:
public class CaricoDTOItemProcessorStep1 implements ItemProcessor<CaricoDTO, CaricoDTO> { private String fileName; private static final Logger log = LoggerFactory.getLogger(CaricoDTOItemProcessorStep1.class); // 注入JdbcTemplate,Spring会自动根据容器中的DataSource完成装配 @Autowired private JdbcTemplate jdbcTemplate; // 可选配置:如果校验规则固定,可提前把校验数据加载到本地缓存大幅提升性能 private Set<String> validCodeSet; @PostConstruct public void initValidCache() { // Bean初始化时一次性查询所有合法的校验值存入缓存,避免每条数据都查库 validCodeSet = new HashSet<>(jdbcTemplate.queryForList("select code from 你的校验码表", String.class)); } @Override public CaricoDTO process(CaricoDTO carico) throws Exception { // 保留原有逻辑 carico.setDataCaricamento(new Date(System.currentTimeMillis())); carico.setFileName(carico.getResource().getFilename()); // 新增字段校验逻辑 // 示例1:直接查库校验,适合校验规则不固定、缓存命中率低的场景 Integer existCount = jdbcTemplate.queryForObject("select count(1) from 你的业务表 where 校验字段 = ?", Integer.class, carico.get你要校验的字段()); if(existCount == null || existCount == 0) { // 校验不通过处理:返回null即可让Spring Batch跳过该条数据不写入数据库,也可以打印日志记录异常 log.warn("数据ID={}校验不通过,已跳过", carico.getId()); return null; } // 示例2:用预加载的缓存校验,性能更高,适合校验规则固定的场景 if(!validCodeSet.contains(carico.getCode())) { log.warn("数据编码={}不合法,已跳过", carico.getCode()); return null; } // 校验通过返回对象进入Writer执行写入 return carico; } // 原有get/set方法保留 public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } }
- 第二步:可选配置,校验异常容错处理
如果希望校验不通过时抛自定义异常而非返回null,同时统计跳过的异常数据,可以在Step定义时添加skip配置:
@Bean public Step step1(JdbcBatchItemWriter<CaricoDTO> step1Writer) { return stepBuilderFactory.get("step1").<CaricoDTO, CaricoDTO>chunk(10) .reader(multiResourceItemReader()) .processor(processorStep1()) .writer(step1Writer) // 新增容错配置:遇到自定义的校验异常时跳过,最多允许跳过100条异常数据 .faultTolerant() .skip(ValidationException.class) .skipLimit(100) .build(); }
注意事项
- 如果你的Step配置了多线程执行,本地缓存需要使用线程安全的集合类如
ConcurrentHashMap、CopyOnWriteArraySet等 - 数据量极大的场景下,不建议每条数据都单独查库,优先采用预加载缓存、批量校验的方案优化性能
- 校验逻辑不要单独开启事务,事务控制统一在Chunk层面处理即可
内容的提问来源于stack exchange,提问作者Rosalba Marotta
相关产品推荐
相关产品推荐

