最近我们在排查一个诡异的 空指针异常,整个分析过程可以说是跌宕起伏,最终的结论也颇具隐蔽性。今天就把这个问题分享出来,希望对大家有所帮助。
问题现象
在系统中,我们有 单据 B,它通过一个 关联 ID
字段与 上级单据 A 关联。
但在某次操作中,我们发现:
- 单据 B 存在,并且存储了 A 的 ID。
- 但查询 A 时,却查不到数据,导致后续代码调用 A 的
get
方法时报空指针异常。
理论上,B 既然存储了 A 的 ID,A 就应该存在,否则 A 的 ID 是怎么来的?
难道 A 被删除了?
然而,代码中并没有删除 A 的逻辑,而且 DBA 查询了数据库日志,确认 A 从未被删除。那么,这就只剩下一种可能:A 从未生成。
代码分析
我们回溯代码,A 和 B 是在同一个事务内生成的,具体逻辑如下:
@Transactional
public void createA() {
DB生成单据A;
执行业务方法C;
DB生成单据B;
}
代码逻辑很简单:
- 第一步 生成 A。
- 第二步 执行 业务方法 C。
- 第三步 生成 B,并存储 A 的 ID。
由于 B 存储了 A 的 ID,说明 DB生成单据A
代码应该成功执行了。但为什么 A 最终没有出现在数据库中?
难道是