本期重点 会带大家完成【电商实战项目】的轮播图删除功能,用到的知识点包括:
ORM链式操作 如何优雅的进行时间维护 软删除和物理删除的区别 如何优雅的实现软删除 结合商业项目需求,有哪些容易踩的坑?
ORM链式操作-时间维护 需要注意,该特性仅对链式操作有效。
gdb模块支持对数据记录的写入、更新、删除时间自动填充,提高开发维护效率。为了便于时间字段名称、类型的统一维护,如果使用该特性,我们约定:
字段应当设置允许值为null。 字段的类型必须为时间类型,如:date, datetime, timestamp。不支持数字类型字段,如int。 字段的名称不支持自定义设置,并且固定名称约定为: created_at用于保存记录的创建时间,仅会写入一次。
updated_at用于保存记录的修改时间,每次记录变更时更新。
deleted_at用于保存记录的软删除特性,只有当记录删除时会写入一次。
字段名称其实不区分大小写,也会忽略特殊字符,例如CreatedAt, UpdatedAt, DeletedAt也是支持的。此外,时间字段名称可以通过配置文件进行自定义修改,并可使用TimeMaintainDisabled配置完整关闭该特性,具体请参考 ORM使用配置 章节。
对时间类型的固定其实是为了形成一种规范。
特性的启用 当数据表包含created_at、updated_at、deleted_at任意一个或多个字段时,该特性自动启用。
以下的示例中,我们默认示例中的数据表均包含了这3个字段。
created_at写入时间 在执行Insert/InsertIgnore/BatchInsert/BatchInsertIgnore方法时自动写入该时间,随后保持不变。
复制 // INSERT INTO `user`( `name`, `created_at`, `updated_at`) VALUES ( 'john' , `2020- 06 - 06 21 : 00 : 00 `, `2020- 06 - 06 21 : 00 : 00 `)
g.Model ( "user" ) .Data ( g.Map { "name" : "john" } ) .Insert ( )
// INSERT IGNORE INTO `user`( `uid`, `name`, `created_at`, `updated_at`) VALUES ( 10000 , 'john' , `2020- 06 - 06 21 : 00 : 00 `, `2020- 06 - 06 21 : 00 : 00 `)
g.Model ( "user" ) .Data ( g.Map { "uid" : 10000 , "name" : "john" } ) .InsertIgnore ( )
// REPLACE INTO `user`( `uid`, `name`, `created_at`, `updated_at`) VALUES ( 10000 , 'john' , `2020- 06 - 06 21 : 00 : 00 `, `2020- 06 - 06 21 : 00 : 00 `)
g.Model ( "user" ) .Data ( g.Map { "uid" : 10000 , "name" : "john" } ) .Replace ( )
// INSERT INTO `user`( `uid`, `name`, `created_at`, `updated_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`) , `updated_at`= VALUES ( `updated_at`)
g.Model ( "user" ) .Data ( g.Map { "uid" : 10001 , "name" : "john" } ) .Save ( )
需要注意的是Replace方法也会更新该字段,因为该操作相当于删除已存在的旧数据并重新写一条数据。
updated_at更新时间 在执行Insert/InsertIgnore/BatchInsert/BatchInsertIgnore方法时自动写入该时间,在执行Save/Update时更新该时间(注意当写入数据存在时会更新updated_at时间,不会更新created_at时间)。
复制 // UPDATE `user` SET `name`= 'john guo' , `updated_at`= '2020-06-06 21:00:00' WHERE name= 'john'
g.Model ( "user" ) .Data ( g.Map { "name" : "john guo" } ) .Where ( "name" , "john" ) .Update ( )
// UPDATE `user` SET `status`= 1 , `updated_at`= '2020-06-06 21:00:00' ORDER BY `login_time` asc LIMIT 10
g.Model ( "user" ) .Data ( "status" , 1 ) .Order ( "login_time asc" ) .Limit ( 10 ) .Update ( )
// INSERT INTO `user`( `id`, `name`, `update_at`) VALUES ( 1 , 'john guo' , '2020-12-29 20:16:14' ) ON DUPLICATE KEY UPDATE `id`= VALUES ( `id`) , `name`= VALUES ( `name`) , `update_at`= VALUES ( `update_at`)
g.Model ( "user" ) .Data ( g.Map { "id" : 1 , "name" : "john guo" } ) .Save ( )
需要注意的是Replace方法也会更新该字段,因为该操作相当于删除已存在的旧数据并重新写一条数据。
deleted_at数据软删除 软删除会稍微比较复杂一些,当软删除存在时,所有的查询语句都将会自动加上deleted_at的条件。
复制 // UPDATE `user` SET `deleted_at`= '2020-06-06 21:00:00' WHERE uid= 10
g.Model ( "user" ) .Where ( "uid" , 10 ) .Delete ( )
查询的时候会发生一些变化,例如:
复制 // SELECT * FROM `user` WHERE uid> 1 AND `deleted_at` IS NULL
g.Model ( "user" ) .Where ( "uid>?" , 1 ) .All ( )
可以看到当数据表中存在deleted_at字段时,所有涉及到该表的查询操作都将自动加上deleted_at IS NULL的条件
联表查询的场景 如果关联查询的几个表都启用了软删除特性时,会发生以下这种情况,即条件语句中会增加所有相关表的软删除时间判断。
复制 // SELECT * FROM `user` AS `u` LEFT JOIN `user_detail` AS `ud` ON (ud.uid=u.uid) WHERE u.uid=10 AND `u`.`deleted_at` IS NULL AND `ud`.`deleteat` IS NULL LIMIT 1
g.Model("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid").Where("u.uid", 10).One()
Unscoped忽略时间特性 Unscoped用于在链式操作中忽略自动时间更新特性,例如上面的示例,加上Unscoped方法后:
复制 // SELECT * FROM `user` WHERE uid>1
g.Model("user").Unscoped().Where("uid>?", 1).All()
// SELECT * FROM `user` AS `u` LEFT JOIN `user_detail` AS `ud` ON (ud.uid=u.uid) WHERE u.uid=10 LIMIT 1
g.Model("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid").Where("u.uid", 10).Unscoped().One()
以上内容来源自官方文档:https://goframe.org/pages/viewpage.action?pageId=1114139
软删除和物理删除的区别 软删除也叫标记删除,通过字段标记DB中的纪录是否被删除: 比如通过is_delete字段标记,默认为0,删除时设置为1
或者和视频内容一样,使用deleted_at字段标记删除的时间,默认为null
如何优雅的实现软删除 如果你详细看完了ORM链式操作-时间维护这部分内容,想必心中一定有了答案。
结合商业项目需求,有哪些容易踩的坑? 一定要结合实际情况决定使用物理删除还是软删除,下面的例子抛转引玉:
1. 比如管理后台删除轮播图这种操作建议使用软删除。因为可能出现误操作的情况,软删除可以及时找回;而且轮播图的数据往往不多,冗余保存也是没有问题的。
2. 再比如用户移除收藏文章的记录,建议物理删除。原因是收藏文章,取消收藏这类操作比较随意,没有任何风险。再者这类数据量比较庞大,软删除没有意义,反而会增加收藏操作的逻辑压力和DB压力。
本文转载自微信公众号「 程序员升级打怪之旅」,作者「王中阳Go」,可以通过以下二维码关注。
转载本文请联系「 程序员升级打怪之旅」公众号。