TypeORM自定义EntityManager事务无法调用自定义方法的问题
解决TypeORM自定义EntityManager事务中无法调用扩展方法的问题
问题根源
TypeORM原生transaction方法返回的是EntityManager父类实例,而非我们自定义的CustomEntityManager子类,所以回调里拿到的transactionManager没有我们扩展的customSoftDelete等方法——编译时因为类型声明能通过,但运行时会报错。
以下是几种可行的修复方案:
方案一:重写transaction方法,返回CustomEntityManager实例
这是最稳妥的长期解决方案,直接在自定义类中重写事务方法,把原生管理器包装成子类实例传入回调:
import { EntityManager } from "typeorm"; class CustomEntityManager extends EntityManager { // 自定义软删除方法 async customSoftDelete(entity: any) { // 你的软删除逻辑,比如更新deletedAt字段 return this.update(entity.constructor, entity.id, { deletedAt: new Date() }); } // 重写自定义事务方法 async customTransaction<T>(callback: (manager: CustomEntityManager) => Promise<T>): Promise<T> { return super.transaction(async (rawManager: EntityManager) => { // 用原生管理器的连接和查询器创建CustomEntityManager实例 const customManager = new CustomEntityManager(rawManager.connection, rawManager.queryRunner); return callback(customManager); }); } }
这样回调里拿到的manager就是CustomEntityManager实例,直接调用customSoftDelete不会有问题,同时完全复用了原生事务的上下文。
方案二:抽离自定义方法为工具函数(解耦方案)
如果不想修改EntityManager子类的事务逻辑,可以把扩展方法抽成独立工具函数,依赖传入的EntityManager:
// 单独的工具函数文件 export async function customSoftDelete(manager: EntityManager, entity: any) { return manager.update(entity.constructor, entity.id, { deletedAt: new Date() }); } // 自定义EntityManager类 class CustomEntityManager extends EntityManager { async customSoftDelete(entity: any) { return customSoftDelete(this, entity); } // 事务方法直接复用父类,回调传原生manager async customTransaction<T>(callback: (manager: EntityManager) => Promise<T>): Promise<T> { return super.transaction(callback); } }
使用时在事务回调里直接调用工具函数:
await customEntityManager.customTransaction(async (manager) => { await customSoftDelete(manager, targetEntity); });
这种方式彻底避免了类型不匹配的问题,同时保持代码的可复用性。
方案三:临时类型断言+原型修补(仅应急用)
如果是临时修复不想改动太多代码,可以用类型断言配合原型修补,但这是hack手段,不推荐长期使用:
await customEntityManager.customTransaction(async (manager) => { // 修补原型链,让manager拥有CustomEntityManager的方法 Object.setPrototypeOf(manager, CustomEntityManager.prototype); // 类型断言为自定义类 const customManager = manager as CustomEntityManager; await customManager.customSoftDelete(targetEntity); });
这种方式可能会破坏TypeORM内部的实例结构,后续版本升级有风险,仅适合临时救急。
内容的提问来源于stack exchange,提问作者Julian Mendez
相关产品推荐
相关产品推荐

