Sequelize调用findAll返回空数组但表内存在数据该如何解决
问题原因
- 软删除配置异常:如果Payments模型开启了
paranoid: true软删除配置,写入数据时误填了deletedAt字段为非空值,或是模型配置的软删除字段名与表实际字段不匹配,findAll默认会过滤掉deletedAt不为null的数据,就会无报错返回空数组。因为其他表查询正常,该问题为Payments模型独有配置导致的概率最高。 - 写入事务未提交:第一次创建数据的操作在未提交的事务中执行,后续查询没有加入同一个事务,导致查询时读取不到未提交的事务数据。
- 模型表映射错误:检查Payments模型的
tableName配置是否和实际操作的表名完全一致,是否存在大小写不匹配、表名后缀错误问题;另外检查是否给Payments单独配置了其他schema/数据库名,导致写入和查询不在同一个库中。 - 默认作用域带过滤条件:Payments模型配置了
defaultScope默认作用域,内置了隐藏的where过滤条件,未主动清除作用域的情况下所有查询都会自带过滤规则,导致返回空数组。
解决方法
- 软删除排查:先执行
Payments.findAll({ paranoid: false })测试,如果可以查到数据,确认是软删除逻辑导致。检查写入逻辑是否误设置了deletedAt字段值,或是调整模型的paranoid配置适配业务需求。 - 事务逻辑校验:确认创建数据的逻辑是否开启了事务却未执行
commit提交,将写入和查询操作放入同一个事务,或是写入完成后手动提交事务即可。 - 打印实际执行SQL定位:修改查询代码开启日志,输出生成的原生SQL:
[err, all_payments] = await to(Payments.findAll({ logging: console.log }));
将生成的SQL直接放到数据库中执行,若执行也返回空则说明SQL自带过滤条件,若能查到数据则属于Sequelize配置层面问题,可快速缩小排查范围。
- 清除默认作用域测试:执行
Payments.unscoped().findAll()测试,如果可正常返回数据,说明默认作用域配置了隐藏过滤规则,检查模型的defaultScope配置调整即可。 - 核对表映射关系:打印
Payments.tableName确认映射的表名是否正确,检查模型是否配置了独立的schema参数,确认写入和查询的库、表完全一致。
内容的提问来源于stack exchange,提问作者BlackThorn
相关产品推荐
相关产品推荐

