TypeORM Decimal类型列使用QueryBuilder查询返回字符串而非数字问题求解
问题原因
这是TypeORM底层数据库驱动的默认行为:JavaScript原生number类型存在精度上限(最大安全值为2^53 - 1),而数据库的decimal类型支持更高精度,为了避免精度丢失,驱动默认会把decimal类型的返回值序列化为字符串。
修复方案
下面提供三种适配不同场景的解决方案:
方案1:全局配置自动转换
如果你的项目中所有decimal字段的精度都不会超过16位,不会触发JS的精度丢失问题,可以直接在TypeORM连接配置中添加参数,全局开启decimal自动转数值的能力,以MySQL为例:
// typeorm配置文件 export default { type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: '你的数据库密码', database: '你的数据库名', entities: [CollectionStats], synchronize: false, // 新增以下配置 extra: { decimalNumbers: true } }
配置生效后,所有查询返回的decimal字段都会自动转为number类型,普通find查询和QueryBuilder查询都生效。
方案2:针对指定字段添加转换器
如果不需要全局修改,只想处理部分decimal字段,可以在实体的Column装饰器中添加自定义转换器:
// 先定义通用转换器 const decimalTransformer = { // 数据入库时的转换逻辑,直接传入数值即可 to: (value: number) => value, // 查询返回时的转换逻辑,将字符串转为数值 from: (value: string) => parseFloat(value) } // 实体字段修改为如下写法 @Column("decimal", { transformer: decimalTransformer }) one_day_volume: number; // 其余需要转换的decimal字段都按上述格式修改即可
如果你的decimal字段精度很高,担心转number丢失精度,也可以将from方法的返回值改为高精度实例,比如引入big.js后返回Big(value)即可。
方案3:单次查询手动转换
如果只是临时处理某一次QueryBuilder的查询结果,可以拿到返回值后手动做类型转换:
const result = await dataSource .getRepository(CollectionStats) .createQueryBuilder('stats') .where('stats.id = :id', { id: 1 }) .getOne() // 手动转换字段类型 result.one_day_volume = parseFloat(result.one_day_volume as unknown as string)
内容的提问来源于stack exchange,提问作者user16780074
相关产品推荐
相关产品推荐

