时间更新

gdb模块支持对数据记录的写入、更新、删除时间自动填充,提高开发维护效率。为了便于时间字段名称、类型的统一维护,如果使用该特性,我们约定:

  • 字段应当设置允许值为null
  • 字段的类型必须为时间类型,如datetime, timestamp。不支持数字类型字段,如int
  • 字段的名称不支持自定义设置,并且固定名称约定为:
    • create_at用于记录创建时更新,仅会写入一次。
    • update_at用于记录修改时更新,每次记录变更时更新。
    • delete_at用于记录的软删除特性,只有当记录删除时会写入一次。

字段名称其实不区分大小写,也不判断特殊字符,例如CreateAt, UpdateAt, DeleteAt也是支持的。

特性的启用

当数据表包含create_atupdate_atdelete_at任意一个或多个字段时,该特性自动启用。

以下的示例中,我们默认示例中的数据表均包含了这3个字段。

create_at写入时间

  1. // INSERT INTO `user`(`name`,`create_at`,`update_at`) VALUES('john', `2020-06-06 21:00:00`, `2020-06-06 21:00:00`)
  2. r, err := db.Table("user").Data(g.Map{"name": "john"}).Insert()
  3. // INSERT IGNORE INTO `user`(`uid`,`name`,`create_at`,`update_at`) VALUES(10000,'john', `2020-06-06 21:00:00`, `2020-06-06 21:00:00`)
  4. r, err := db.Table("user").Data(g.Map{"uid": 10000, "name": "john"}).InsertIgnore()
  5. // REPLACE INTO `user`(`uid`,`name`,`create_at`,`update_at`) VALUES(10000,'john', `2020-06-06 21:00:00`, `2020-06-06 21:00:00`)
  6. r, err := db.Table("user").Data(g.Map{"uid": 10000, "name": "john"}).Replace()
  7. // INSERT INTO `user`(`uid`,`name`,`create_at`,`update_at`) VALUES(10001,'john', `2020-06-06 21:00:00`, `2020-06-06 21:00:00`) ON DUPLICATE KEY UPDATE `uid`=VALUES(`uid`),`name`=VALUES(`name`),`update_at`=VALUES(`update_at`)
  8. r, err := db.Table("user").Data(g.Map{"uid": 10001, "name": "john"}).Save()

update_at更新时间

  1. // UPDATE `user` SET `name`='john guo',`update_at`='2020-06-06 21:00:00' WHERE name='john'
  2. r, err := db.Table("user").Data(g.Map{"name" : "john guo"}).Where("name", "john").Update()
  3. // UPDATE `user` SET `status`=1,`update_at`='2020-06-06 21:00:00' ORDER BY `login_time` asc LIMIT 10
  4. r, err := db.Table("user").Data("status", 1).Order("login_time asc").Limit(10).Update()

delete_at数据软删除

软删除会稍微比较复杂一些,当软删除存在时,所有的查询语句都将会自动加上delete_at的条件。

  1. // UPDATE `user` SET `delete_at`='2020-06-06 21:00:00' WHERE uid=10
  2. r, err := db.Table("user").Where("uid", 10).Delete()

查询的时候会发生一些变化,例如:

  1. // SELECT * FROM `user` WHERE uid>1 AND `delete_at` IS NULL
  2. r, err := db.Table("user").Where("uid>?", 1).All()

可以看到当数据表中存在delete_at字段时,所有涉及到该表的查询操作都将自动加上delete_at IS NULL的条件

联表查询的场景

如果关联查询的几个表都启用了软删除特性时,会发生以下这种情况,即条件语句中会增加所有相关表的软删除时间判断。

  1. // SELECT * FROM `user` AS `u` LEFT JOIN `user_detail` AS `ud` ON (ud.uid=u.uid) WHERE u.uid=10 AND `u`.`delete_at` IS NULL AND `ud`.`deleteat` IS NULL LIMIT 1
  2. r, err := db.Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid").Where("u.uid", 10).One()

Unscoped忽略软删除

Unscoped用于在链式操作中忽略软删除时间条件,例如上面的示例,加上Unscoped方法后:

  1. // SELECT * FROM `user` WHERE uid>1
  2. r, err := db.Table("user").Unscoped().Where("uid>?", 1).All()
  3. // SELECT * FROM `user` AS `u` LEFT JOIN `user_detail` AS `ud` ON (ud.uid=u.uid) WHERE u.uid=10 LIMIT 1
  4. r, err := db.Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid").Where("u.uid", 10).Unscoped().One()