这是我参与「第五届青训营 」伴学笔记创作活动的第 13 天
三件套简介
Gorm: ORM框架
Kitex: Golang微服务的RPC框架,高性能,强可扩展性的,支持多协议,
Hertz: HTTP框架,具有高易用性,高性能,高扩展性
Gorm的CRUD
type Product struct{
Code string
Price uint
}//定义结构
funcm (p Product) TableName() string{
return "product"
}//返回表名
func main(){
db, err:=gorm.Open(
mysql.Open(dsn: "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=local"),
&gorm.Config{}
)//初始化mysql的数据库连接
if err != nil{
panic("failed to connect database")
}
db.Create(&Product{Code:"D42", Price:100})//创建数据
var product Product
db.First(&product, 1)//默认基于整形主键查找
db.Model(&product, "code=?","D42")//查询code为D42的记录,first只能查单个记录,find可以多个
db.Model(&product).Update("Price", 200)//更新单列数据
db.Model(&product).Updates(Product{Price:200, Code:"F42"})//更新多列
db.Model(&product).Updates(map[string]interface{}{"Price":200, "Code": "F42"})
db.Delete(&product, 1)//删除
}
- 在没有定义表名称时会使用结构体的蛇形负数作为表名称,字段名的蛇形作为列名。
- 使用CreateAt,UpdateAt字段作为创建和更新时间
连接数据库
Gorm以驱动的方式支持数据库,包括MySQL, SQLServer,PostgreSQL等。DSN包含了连接数据库的信息。
创建数据
type Product struct{
code string `gorm:"column:co"`
name string `gorm:"default:"`
}
p := &Product{Code:"D42"}
db.Create(p)
db.Clauses(clause.OnConflict{DoNothing:true}).Create(&p)
- 通过gorm的标签定义列名称,通过default标签定义默认值,通过primarykey设置主键
- 创建数据可能出现唯一索引冲突,使用clause.OnConflict来避免数据冲突
查询数据
u:=&User{}
db.First(u)
db.Where("age>10").find(&users)//where语句还支持传递结构体和map
-
First查不到数据会返回ErrRecordNotFound导致程序出错, 使用Find查询多条数据,查询不到数据不会返回错误
-
使用结构体注意只会查询非0值字段,所以值为空,是不用于构建查询的,这时候使用map,或gorm提供的select实现。
更新数据
db.Model(&User{ID:111})..Updates(map[string]interface{}{"name":"hello", "age":18,"actived":false})
- 用model设置表名,使用结构体更新多个列。
删除数据
物理删除
db.Delete(&Usr{},10)
软删除
type User struct{
ID int64
Age int64
Deleted gorm.DeletedAt
}
u:=User{ID:111}
db.Delete(&u)
-
gorm.DeleteAt来实现软删除,拥有软删除能力的Model调用delete时,记录不会被从数据库中真正删除,但gorm会将deletedAt置为当前时间,而且不能通过正常查询方法找到该记录,使用Unscoped可以查到被软删的数据
-
动词语句如create update会直接调用sql语句,所以在create后面跟where是不会生效的。where是用来拼凑SQL的,查询结果需要暂时用result来保留。
Gorm事务
- 手动执行提供Begin Commit Rollback等方法使用事务,而自动执行使用transacation。
tx:=db.Begin()//固化一个链接而不是使用连接池的连接,开启事务,
if err = tx.Create(&User(Name:"name")).Error;err!=nil{
tx.Rollback()
return
}
if err =tx.Create(&User{Name:"name1"}).Error;err!=nil{
tx.Rollback()//忘记rollback可能导致链接泄漏
return
}
tx.Commit
//transaction自动提交事务
db.Transaction(func(tx * gorm.DB) err {
if err = tx.Create(&User{Name:"hi"}).Error; err != nil{
return err
}
if err = tx.Create(&User{Name:"u"}).Error; err != nil{
return err
}
return nil
);
hook
func (u *User) BeforeCreate(tx *gorm.DB) (err error)
func (u *User) AfterCreate(tx * gorm.DB) (err error)
-
gorm提供了crud的hook功能, hook是在创建,查询等操作之前和之后调用的函数,如果任何hook返回错误,gorm将停止后续的操作并回滚事务。
-
gorm会开启一个默认事务,hook会包含在该事务内。
性能提高
-
PrepareStmt缓存预编译语句可以提高后续调用速度。
-
写操作,为了确保数据的完整性,GORM会默认封装在事务中,会降低性能。在部分情况下可以SkipDefaultTransaction关闭默认事务,
常用扩展
-
GORM代码生成工具 github.com/go-gorm/gen
-
GORM分片库方案 github.com/go-gorm/sha…
-
GORM手动索引 github.com/go-gorm/hin…
-
GORM乐观锁 github.com/go-gorm/opt…
-
GORM读写分离 github.com/go-gorm/dbr…
-
GORM OpenTelemetry扩展 github.com/go-gorm/ope…