GORM学习 | | 青训营笔记

108 阅读3分钟

这是我参加第「第五届青训营 」伴学笔记创作活动的第五天。

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缓存预编译语句,可以提高后续调用的速度。

GORM生态