TypeGraphQL中字段解析器写入数据库是否合规?附代码示例
在TypeGraphQL中使用字段解析器写入数据库的可行性分析
结论:可行,但存在设计层面的隐患
从功能实现角度,你提供的代码是可以正常运行的——TypeGraphQL并没有禁止字段解析器(FieldResolver)执行数据库写入操作,异步的字段解析器本身支持包含数据库交互的逻辑,你的代码确实能实现「每次查询该字段时生成新token并保存到数据库」的需求。
但这种写法违背了GraphQL的设计原则,还会带来一些实际问题:
- 违反查询语义:GraphQL约定
Query类型的操作是只读的,数据修改应该通过Mutation完成。用查询操作触发数据库变更,会让API使用者产生误解,不符合接口的语义规范。 - 副作用不可控:如果这个字段被包含在批量查询、嵌套查询中,会触发多次不必要的数据库写入,可能导致性能损耗或数据不一致。
- 调试成本高:后续排查数据变更记录时,很难追踪到是哪次查询操作触发的修改,增加维护难度。
更合理的替代方案
把生成并保存signatureToken的逻辑迁移到Mutation中,比如定义一个专门的变更操作:
@Mutation(() => String) async generateSignatureToken( @Arg("addressId") addressId: string, @Ctx() { em }: WithRequiredOnly<Context, "em"> ): Promise<string> { const address = await em.findOne(Address, { id: addressId }); if (!address) { throw new Error("Address not found"); } const newSignatureToken = uuidv4(); address.signatureToken = newSignatureToken; address.signatureTokenCreated = new Date(); await em.save(address); return newSignatureToken; }
这样既符合GraphQL的语义规范,也能明确控制数据修改的触发时机,避免不必要的副作用。
原代码参考
@FieldResolver(() => String) async signatureToken( @Root() address: Address, @Ctx() { em }: WithRequiredOnly<Context, "em"> //entity manager of the database (typeorm) ): Promise<string> { // ! Is it okay for a fieldresolver to modify the database? const newSignatureToken = uuidv4(); address.signatureToken = newSignatureToken; address.signatureTokenCreated = new Date(); await em.save(address) // Save the new address with signatureToken to the database return newSignatureToken; }
内容的提问来源于stack exchange,提问作者sev
相关产品推荐
相关产品推荐

