为何查询表数据时@UpdateDateColumn字段会自动更新?
核心原因
数据库与ORM更新逻辑冲突
你给数据库表的changeDate字段设置了ON UPDATE CURRENT_TIMESTAMP(6),这会让MySQL在该行发生任何UPDATE操作时自动更新该字段。但同时使用了TypeORM的@UpdateDateColumn装饰器,该装饰器的设计是由ORM层在执行save/update等写操作时自动更新字段值,两者叠加导致更新逻辑混乱。表结构与实体类不匹配触发隐性写操作
实体里flavor标记为nullable: true,但数据库表中该字段是NOT NULL,这种不一致会让TypeORM在加载实体时触发隐性的修正操作(比如试图将null值改为默认值),而你的数据库是只读权限,直接阻断了这个写操作,抛出报错。
另外,@UpdateDateColumn会被ORM视为需要跟踪变化的字段,一旦实体状态被ORM判定为“已修改”(哪怕是结构不匹配导致的误判),就会尝试执行UPDATE,进而触发只读权限报错。
解决步骤
移除数据库层面的自动更新设置
既然用了@UpdateDateColumn,就交给ORM管理更新,修改changeDate的表字段定义,移除ON UPDATE CURRENT_TIMESTAMP(6):`changeDate` datetime(6) DEFAULT CURRENT_TIMESTAMP(6),若不需要数据库默认值,也可直接定义为
datetime(6)。对齐实体类与表结构
要么修正实体里的flavor字段为非 nullable,要么修改数据库表允许该字段为null:- 实体修改:
@Column() flavor: string; - 数据库修改:
`flavor` varchar(255) DEFAULT NULL,
- 实体修改:
使用纯查询避免ORM隐性操作
如果仅需读取数据,用createQueryBuilder执行原生风格的查询,完全规避ORM的状态跟踪逻辑:const cake = await this.cakeRepository.createQueryBuilder('cake') .select(['cake.id', 'cake.GUID', 'cake.changeDate']) .where('cake.GUID = :guid', { guid }) .getOne();
文档补充说明
TypeORM官方文档明确说明,@UpdateDateColumn会在实体执行save或update时自动更新为当前时间,无需依赖数据库层面的ON UPDATE设置。同时,实体类与数据库表结构的严格一致是避免ORM产生意外写操作的关键前提。
内容的提问来源于stack exchange,提问作者Manuel Duarte

