使用Mikro-ORM+GraphQL遇ValidationError,求正确实现RequestContext
解决Mikro-ORM全局EntityManager引发的ValidationError
这个错误是Mikro-ORM的安全限制:全局EntityManager实例并非请求上下文隔离的,直接用它执行数据库操作会存在并发请求下的数据污染风险,因此框架禁止这种用法。以下是无需禁用验证的标准解决方案:
步骤1:添加RequestContext中间件
在服务入口(比如index.ts)中,为每个请求创建独立的RequestContext,确保EntityManager在请求范围内隔离。以Apollo Server + Express为例:
import { RequestContext } from '@mikro-orm/core'; import { ApolloServer } from 'apollo-server-express'; import express from 'express'; async function bootstrap() { const app = express(); // 初始化Mikro-ORM(保留你原有的配置) const orm = await MikroORM.init({ type: 'postgresql', // 你的数据库类型 dbName: 'your_db_name', entities: [Post], // 其他配置... }); // 注册RequestContext中间件,每个请求创建独立上下文 app.use((req, res, next) => { RequestContext.create(orm.em, next); }); // 创建Apollo Server const apolloServer = new ApolloServer({ schema: await buildSchema({ resolvers: [PostResolver], }), // 上下文传递当前请求的EntityManager context: () => ({ em: orm.em }), }); await apolloServer.start(); apolloServer.applyMiddleware({ app }); app.listen(4000, () => { console.log('Server running at http://localhost:4000/graphql'); }); } bootstrap().catch(err => console.error(err));
步骤2:在Resolver中使用上下文的EntityManager
修改PostResolver,从GraphQL上下文中获取EntityManager,而非直接调用全局实例:
import { Resolver, Query, Ctx } from 'type-graphql'; import { Post } from './entities/Post'; import { EntityManager } from '@mikro-orm/core'; @Resolver(Post) export class PostResolver { @Query(() => [Post]) posts(@Ctx() { em }: { em: EntityManager }) { return em.find(Post, {}); } }
原理说明
RequestContext.create()会为每个请求绑定一个独立的EntityManager作用域,所有在该请求内的数据库操作都会使用这个隔离的实例,既避免了并发数据冲突,也符合Mikro-ORM的设计规范,因此不会触发验证错误。
验证
重启服务后执行查询{ posts { id createdAt updatedAt title } },即可正常返回数据。
内容的提问来源于stack exchange,提问作者Karthik Venkatesh
相关产品推荐
相关产品推荐

