如何在Prisma中添加保存前/保存后中间件?
Prisma 实现类似 Mongoose 文档保存前后钩子功能的方法
Prisma 提供了完全对应的能力来实现你提到的需求,核心通过两类能力实现:
- 全局中间件(Prisma Middleware):可以在所有数据库查询执行的前后插入自定义逻辑,覆盖全模型的写操作拦截需求
- 扩展客户端 Query 钩子:Prisma 4.16+ 新增的细粒度钩子能力,可以针对单个模型的单个操作绑定自定义逻辑,使用更灵活
核心场景实现示例
1. 保存前自定义逻辑
可以在查询执行前拿到入参,完成字段校验、值修改、权限校验等操作,和 Mongoose pre('save') 能力完全对齐:
const prisma = new PrismaClient() // 全局中间件写法 prisma.$use(async (params, next) => { // 只拦截 User 模型的创建操作 if (params.model === 'User' && params.action === 'create') { const createData = params.args.data // 示例:入库前自动加密密码 createData.password = await bcrypt.hash(createData.password, 10) } return next(params) })
2. 保存后自定义逻辑
在查询执行完成后可以拿到返回的文档实例,完成日志记录、缓存更新、返回值裁剪等操作,对应 Mongoose post('save') 能力:
// 细粒度 Query 钩子写法 const prisma = new PrismaClient().$extends({ query: { post: { async update({ args, query }) { // 执行原始更新操作 const updatedPost = await query(args) // 后置逻辑:更新完成后记录操作日志 console.log(`帖子${updatedPost.id}已更新,更新人:${args.data.updaterId}`) // 裁剪敏感字段后返回给上层 delete updatedPost.internalAuditInfo return updatedPost } } } })
3. 获取字段变更情况
在更新操作的前置阶段,先查询原始数据和传入的更新字段做比对,即可得到完整的变更详情:
prisma.$use(async (params, next) => { if (params.model === 'Order' && params.action === 'update') { // 先查询变更前的原始数据 const originOrder = await prisma.order.findUnique({ where: params.args.where }) // 提取所有待变更的字段 const updateFields = Object.keys(params.args.data) // 生成变更前后对比结果 const changeLog = updateFields.map(field => ({ fieldName: field, before: originOrder[field], after: params.args.data[field] })) // 可以把变更日志存到专门的审计表 await prisma.auditLog.create({ data: { content: changeLog } }) } return next(params) })
内容的提问来源于stack exchange,提问作者Gergő Horváth
相关产品推荐
相关产品推荐

