从v2.8
版本开始,如果时间字段created_at
、 updated_at
、 deleted_at
为整型字段,ORM组件会自动识别支持,并写入秒级的时间戳数值。
示例SQL
这是后续示例代码中用到的MySQL
表结构。
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`status` tinyint DEFAULT 0,
`created_at` int(10) unsigned DEFAULT NULL,
`updated_at` int(10) unsigned DEFAULT NULL,
`deleted_at` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `user_detail` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`address` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
tip
如果您尝试测试查看ORM
操作执行的SQL
语句,建议您打开debug
模式(相关文档:调试模式),SQL
语句将会自动打印到日志输出。
created_at
写入时间
在执行 Insert/InsertIgnore/BatchInsert/BatchInsertIgnore
方法时自动写入该时间,随后的更新/删除操作不会引起created_at
字段内容的改变。
warning
需要注意的是 Replace
方法也会更新该字段,因为该操作相当于删除已存在的旧数据并重新写一条数据。
// INSERT INTO `user`(`name`,`created_at`,`updated_at`,`deleted_at`) VALUES('john',1731481488,1731481488,0)
g.Model("user").Data(g.Map{"name": "john"}).Insert()
// INSERT IGNORE INTO `user`(`id`,`name`,`created_at`,`updated_at`,`deleted_at`) VALUES(10000,'john',1731481518,1731481518,0)
g.Model("user").Data(g.Map{"id": 10000, "name": "john"}).InsertIgnore()
// REPLACE INTO `user`(`id`,`name`,`created_at`,`updated_at`,`deleted_at`) VALUES(10000,'john',1731481747,1731481747,0)
g.Model("user").Data(g.Map{"id": 10000, "name": "john"}).Replace()
// INSERT INTO `user`(`id`,`name`,`created_at`,`updated_at`,`deleted_at`) VALUES(10001,'john',1731481766,1731481766,0) ON DUPLICATE KEY UPDATE `id`=VALUES(`id`),`name`=VALUES(`name`),`updated_at`=VALUES(`updated_at`),`deleted_at`=VALUES(`deleted_at`)
g.Model("user").Data(g.Map{"id": 10001, "name": "john"}).Save()
deleted_at
数据软删除
当软删除存在时(即deleted_at
字段存在时),所有的查询语句都将会自动加上 deleted_at
的条件。
// UPDATE `user` SET `deleted_at`=1731481948 WHERE (`id`=10) AND `deleted_at`=0
g.Model("user").Where("id", 10).Delete()
查询的时候会发生一些变化,例如:
// SELECT * FROM `user` WHERE (id>1) AND `deleted_at`=0
g.Model("user").Where("id>?", 1).All()
可以看到当数据表中存在 deleted_at
字段时,所有涉及到该表的查询操作都将自动加上 deleted_at=0
的条件。
updated_at
更新时间
在执行 Save/Update
方法时自动写入该时间。需要注意的是 Replace
方法也会更新该字段,因为该操作相当于删除已存在的旧数据并重新写一条数据。
info
如果同时存在deleted_at
软删除字段,那么更新操作语句中同样会出现deleted_at
的条件。
// UPDATE `user` SET `name`='john guo',`updated_at`=1731481821 WHERE (`name`='john') AND `deleted_at`=0
g.Model("user").Data(g.Map{"name" : "john guo"}).Where("name", "john").Update()
// UPDATE `user` SET `status`=1,`updated_at`=1731481895 WHERE `deleted_at`=0 ORDER BY `id` ASC LIMIT 10
g.Model("user").Data("status", 1).OrderAsc("id").Limit(10).Update()
// INSERT INTO `user`(`id`,`name`,`created_at`,`updated_at`,`deleted_at`) VALUES(1,'john guo',1731481915,1731481915,0) ON DUPLICATE KEY UPDATE `id`=VALUES(`id`),`name`=VALUES(`name`),`updated_at`=VALUES(`updated_at`),`deleted_at`=VALUES(`deleted_at`)
g.Model("user").Data(g.Map{"id": 1, "name": "john guo"}).Save()
联表查询的场景
如果关联查询的几个表都启用了软删除特性时,会发生以下这种情况,即条件语句中会增加所有相关表的软删除时间判断。
// SELECT * FROM `user` AS `u` LEFT JOIN `user_detail` AS `ud` ON (ud.id=u.id) WHERE (`u`.`id`=10) AND `u`.`deleted_at`=0 LIMIT 1
g.Model("user", "u").LeftJoin("user_detail", "ud", "ud.id=u.id").Where("u.id", 10).One()
控制写入时间粒度
本章节的时间字段数值写入默认是秒级时间戳,但如果我们想要控制时间写入的粒度,写入毫秒级时间戳怎么做呢?我们可以使用SoftTimeOption。