这是我参加第「第五届青训营 」伴学笔记创作活动的第五天。
Gorm基本使用
Gorm的约定:
Gorm使用名为 ID 的字段,作为主键
使用结构体的蛇形负数作为表名
字段名的蛇形作为列名
使用CreatedAt ,UpdatedAt字段作为创建,更新时间
基本使用:
GGORM创建数据
处理唯一标识字段冲突:
如何使用Upsert(gorm只支持根据id来判断,如果对应id记录存在则更新,不存在则插入)(即当id已存在时的处理方式)
使用clause.OnConflict处理数据冲突:
// 已不处理冲突为例,创建一条数据
p := &Product{Code:"D42", ID:1}
db.Clauses(clause.OnConflict{DoNothing:true}).Create(&p)
使用默认值:
GORM查询数据
First问题:
使用First时需要注意查询不到数据时会返回ErrRecordNotFound。
使用Find查询多条数据,查询不到数据不会返回错误。
使用结构体作为查询条件时,GORM只会查询非零值,这意味着如果您的字段值为"0",flase,或其他零值,该字段不会被用于构建查询条件,使用Map来构建查询条件。
GORM更新数据
使用Struct更新时,只会更新非零值,如果需要更新零值可以使用Map更新或使用Select选择字段
GORM删除数据
物理删除
软删除
gorm.DeletedAt
GORM提供了gorm.DeleteAt用于帮助用户实现软删除。
拥有软删除能力的Model调用Delete时,记录不会被从数据库中真正删除,但GORM会将DeleteAt置为当前时间,并且并且不能再通过正常的查询方法找到该纪录。
可以使用Unscoped来查询到被软删的数据。
GORM事务
事务用来处理数据一致性。
Gorm提供了Begin,Commit,Rollback方法用于使用事务。
注意,从tx :=db.Begin() 开始事务后,接下来的对数据库的操作就需要使用tx而不是db了。db.Begin()返回了一个数据库对象。
db.Begin()执行了两个操作,第一个操作是固化连接,保证使用事务时是同一个连接(不再去用连接池里的连接)。(golang底层对数据库的操作是连接池)第二个操作是执行开启事务的sql语句。
在开发时,如果遇到错误可能会去RollBack,有分支时可能去Commit,但可能会忘记去RollBack或者Commit,导致数据库的连接泄露(?).因为连接泄露,请求量比较大,内存涨上去,导致服务奔溃。
GORM提供了Tansaction方法用来自动提交事务,避免用户漏写Commit,Rollback. (用defer 做panic和error的拦截)
GORM HOOK
HOOK是在创建,查询,更新,删除等操作之前,之后自动调用的函数。
如图,HOOK可以用来做参数校验。
对于写操作(创建,更新,删除),为了确保数据的完整性,GORM会将他们封装在事务内运行 。
但默认事务会降低性能,可以使用SkipDefaultTransaction来关闭默认事务。
使用PrepareStmt缓存预编译语句,可以提高后续调用的速度。