You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Prisma时@updatedAt字段调用.update()后未更新的问题

Prisma @updatedAt 字段在更新关联时未自动更新的解决方案

问题原因

Prisma的@updatedAt注解默认是客户端层面自动更新,仅当直接修改主表(如Channel)的字段时才会触发。你当前的操作是通过connect关联User到Channel,本质上修改的是中间关联表,主表本身的字段没有变化,所以Prisma不会自动更新updatedAt。

另外你提到的DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP是MySQL语法,PostgreSQL不支持这种写法,需要用触发器实现数据库层面的自动更新。


解决方案

方案1:手动显式更新updatedAt

在update操作的data里直接指定updatedAt为当前时间,这是最直接的解决方式:

await this.prismaService.channel.update({
  where: {
    id: channelId,
  },
  data: {
    users: {
      connect: {
        id: userId,
      },
    },
    updatedAt: new Date(), // 手动更新时间戳
  },
  include: channelIncludes,
});

方案2:用Prisma中间件自动处理

如果不想每次关联操作都手动加updatedAt,可以编写Prisma中间件,监听update操作,当检测到关联修改时自动更新主表的updatedAt:

// src/prisma/middleware.ts
import { PrismaClient } from '@prisma/client';

export function addUpdatedAtMiddleware(prisma: PrismaClient) {
  prisma.$use(async (params, next) => {
    // 仅处理update和updateMany操作
    if (params.action === 'update' || params.action === 'updateMany') {
      // 判断data中是否包含关联操作(如connect/disconnect等)
      const hasRelationOp = Object.keys(params.data || {}).some(key => {
        const value = params.data[key];
        return value && typeof value === 'object' && (
          'connect' in value || 'disconnect' in value || 'update' in value ||
          'connectOrCreate' in value || 'delete' in value || 'set' in value
        );
      });

      if (hasRelationOp) {
        params.data.updatedAt = new Date();
      }
    }
    return next(params);
  });
}

然后在NestJS的Prisma服务中注册中间件:

// src/prisma/prisma.service.ts
import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import { addUpdatedAtMiddleware } from './middleware';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    addUpdatedAtMiddleware(this);
    await this.$connect();
  }
}

方案3:数据库层面添加触发器(PostgreSQL)

如果希望从数据库层面强制保证updatedAt自动更新,不受客户端操作影响,可以给channels表添加触发器:

  1. 创建触发器函数:
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
  NEW."updatedAt" = CURRENT_TIMESTAMP;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;
  1. 绑定触发器到channels表:
CREATE TRIGGER update_channels_updated_at
BEFORE UPDATE ON "channels"
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();

注意:同时使用Prisma客户端的@updatedAt和数据库触发器可能导致时间重复更新,建议二选一。如果选择数据库层面实现,可以把模型中的@updatedAt改为@default(now()),避免Prisma客户端干预:

updatedAt DateTime @default(now())

内容的提问来源于stack exchange,提问作者Abdel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 08:26:18