Since version v2.8, if the time fields created_at, updated_at, and deleted_at are integer fields, the ORM component will automatically recognize and support them, writing second-level timestamp values.
Example SQL
This is the MySQL table structure used in the subsequent example code.
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;
If you try to test viewing the SQL statements executed by ORM operations, it's recommended to enable debug mode (related documentation: ORM Senior - Debug Mode), the SQL statements will be automatically printed to log output.
created_at Writing Time
When executing the Insert/InsertIgnore/BatchInsert/BatchInsertIgnore methods, this time is automatically written. Subsequent update/delete operations will not change the content of the created_at field.
It should be noted that the Replace method will also update this field because this operation is equivalent to deleting the existing old data and writing a new data record.
// 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 Soft Delete
When soft deletion is present (i.e., the deleted_at field exists), all query statements will automatically add conditions for deleted_at.
// UPDATE `user` SET `deleted_at`=1731481948 WHERE (`id`=10) AND `deleted_at`=0
g.Model("user").Where("id", 10).Delete()
Changes occur when querying:
// SELECT * FROM `user` WHERE (id>1) AND `deleted_at`=0
g.Model("user").Where("id>?", 1).All()
You can see that when the deleted_at field exists in the data table, all query operations involving the table automatically add the condition deleted_at=0.
updated_at Update Time
When executing the Save/Update methods, this time is automatically written. It should be noted that the Replace method will also update this field because it is equivalent to deleting the existing old data and writing a new data record.
If the deleted_at soft delete field also exists, the update operation statement will also contain the deleted_at condition.
// 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()
Scenarios of Joint Table Queries
If several tables involved in an associated query have enabled the soft delete feature, the following situation will occur, where all relevant tables will have soft deletion time judgment added to the condition statements.
// 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()
Control the Granularity of Time Writing
The time field value writing in this chapter is by default in seconds-level timestamp. But if we want to control the granularity of time writing such as writing a millisecond-level timestamp, how do we do it? We can use Time Fields - SoftTimeOption.