XORM中created/updated自动填充失效的四大原因:字段类型非time.Time、未执行engine.Sync同步表结构、插入前手动赋值覆盖、传值而非传指针。需严格按顺序排查。

在XORM中为结构体字段添加created和updated标签后,数据库插入或更新时时间字段仍为空,说明自动填充机制未生效。
确认结构体字段类型与标签是否匹配
确保字段类型是time.Time,不是string、int64或自定义时间类型。XORM只识别原生time.Time并配合xorm:"created"或xorm:"updated"标签才触发自动赋值。
错误示例:Created string `xorm:"created"` → 不会填充,也不报错,静默失效。
正确写法:Created time.Time `xorm:"created"`。
执行表结构同步(必须步骤)
调用engine.Sync(new(User))或engine.Sync2(new(User)),否则XORM不会将字段的created/updated元信息注册到映射缓存中。
【未执行Sync会导致所有时间标签完全不生效】
这一步必须在首次插入数据前完成,且每次新增/修改含created/updated字段的结构体后都要重新执行。
验证自动填充是否启用
方法一:启用SQL日志观察实际插入语句
engine.ShowSQL(true) → 运行插入操作,查看控制台输出的INSERT语句中是否包含created和updated字段及其值;若字段未出现,说明标签未被识别或Sync未执行。
方法二:手动检查数据库表结构
执行DESCRIBE user;(以user表为例),确认created和updated对应列的默认值是否为CURRENT_TIMESTAMP(MySQL)或类似时间默认约束;XORM Sync会在支持的数据库中自动添加该约束。
注意:SQLite不支持列级默认时间戳,XORM会退回到Go层赋值,因此必须保证插入前结构体实例未手动设置这些字段(否则会覆盖自动值)。
插入/更新时避免手动赋值覆盖
第一步:声明结构体变量时不初始化created/updated字段
✅ 正确:u := User{Name: "Alice", Age: 25} → XORM自动注入当前时间
❌ 错误:u := User{Created: time.Now(), Name: "Alice"} → 手动值优先,自动填充被跳过
第二步:使用Insert()或Update()时传入指针
_, err := engine.Insert(&u) → 必须传&u,传u值拷贝会导致created字段丢失(值拷贝中time.Time零值被传入)
第三步:更新操作中updated字段仅对非零值字段生效
如果结构体中Updated字段已存在非零时间值,XORM默认不再覆盖;需显式置零:u.Updated = time.Time{},再调用Update()才会刷新。

















