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

线程依赖注入问题排查:SQL查询返回NULL触发异常解决方案

问题排查与解决方案:原型线程类注入Repository后查询返回NULL异常

问题梳理

Spring环境中,原型作用域的ExtrusionProcessThread(继承自Thread)注入FiscalCalendarRepository后,执行run方法调用其findReadingVariables查询SQL Server数据库时,extrusionL1DataList返回NULL并触发异常。

排查步骤

  • 验证Repository注入有效性:检查ExtrusionProcessThread实例是否由Spring容器创建,手动new的实例不会触发Spring依赖注入,会导致fiscalCalendarRepository为NULL,调用方法时触发空指针异常。可在run方法开头打印fiscalCalendarRepository引用确认是否为空。
  • 检查Repository方法异常处理:当前findReadingVariables仅捕获EmptyResultDataAccessException,但JDBC操作可能抛出SQL语法错误、数据库连接异常、结果集映射异常等其他未捕获异常,这些异常会直接向上抛出,导致方法无返回值,最终extrusionL1DataList被赋值为NULL。
  • 验证数据库查询有效性:直接执行SELECT * FROM SPC.dbo.manager_l1语句,确认数据库中是否存在数据,以及表名、字段是否与ReadingProcessResponseMapper的映射逻辑匹配。

解决方案

1. 修复Repository方法的异常处理

扩大异常捕获范围,确保任何情况下都返回非NULL的List:

@Override
public List<ReadingProcessResponse> findReadingVariables() {
    StringBuilder query = new StringBuilder();
    query.append("SELECT * FROM SPC.dbo.manager_l1");
    
    try {
        return jdbcTemplate.query(query.toString(), new ReadingProcessResponseMapper());
    } catch (EmptyResultDataAccessException e) {
        return new ArrayList<>();
    } catch (Exception e) { // 捕获所有JDBC相关异常
        e.printStackTrace();
        return new ArrayList<>();
    }
}

2. 确保线程实例由Spring容器创建

  • 避免手动new线程实例,通过ApplicationContext.getBean(ExtrusionProcessThread.class)获取原型Bean,确保Spring完成依赖注入。
  • 改用构造器注入所有依赖,确保实例化时依赖已注入:
@Component
@Scope("prototype")
public class ExtrusionProcessThread extends Thread{
    // 省略其他字段
    private final FiscalCalendarRepository fiscalCalendarRepository;
    
    @Autowired
    public ExtrusionProcessThread(FiscalCalendarRepository fiscalCalendarRepository, 
                                 ReadingProcessRepository readingProcessRepository,
                                 ManagerExtrusionL1Repository managerExtrusionL1Repository,
                                 ManagerExtrusionL3Repository managerExtrusionL3Repository,
                                 EmailService emailService) {
        this.fiscalCalendarRepository = fiscalCalendarRepository;
        this.readingProcessRepository = readingProcessRepository;
        this.managerExtrusionL1Repository = managerExtrusionL1Repository;
        this.managerExtrusionL3Repository = managerExtrusionL3Repository;
        this.emailService = emailService;
    }
    
    // 省略run方法
}

3. 替换Thread继承为Runnable实现(推荐)

Spring生态中更推荐实现Runnable接口,配合TaskExecutor管理线程,避免直接继承Thread带来的容器管理问题:

@Component
@Scope("prototype")
public class ExtrusionProcessTask implements Runnable {
    // 字段与原类一致,构造器注入依赖
    
    @Override
    public void run() {
        // 原run方法逻辑不变
    }
}

使用时通过Spring的TaskExecutor提交任务:

@Autowired
private TaskExecutor taskExecutor;
@Autowired
private ApplicationContext context;

public void startTask(ReadingProcessData data) {
    ExtrusionProcessTask task = context.getBean(ExtrusionProcessTask.class);
    task.setData(data); // 设置必要参数
    taskExecutor.execute(task);
}

4. 补充空值检查

在run方法中添加空值判断,避免后续逻辑因NULL列表触发异常:

if (data.getLine().equals(LineEnum.LINE_1.getCodeLine())) {
    extrusionL1DataList = fiscalCalendarRepository.findReadingVariables();
    if (extrusionL1DataList == null) {
        extrusionL1DataList = new ArrayList<>();
    }
} else {
    extrusionL3DataList = readingProcessRepository.findReadingVariables(PlcVariablesMySqlEnum.TABLE_EXTRUSION_L3.getDescription());
    if (extrusionL3DataList == null) {
        extrusionL3DataList = new ArrayList<>();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:17:48