这是我参与「第五届青训营 」笔记创作活动的第5天
Gorm
迭代10年+的功能强大的ORM框架
使用
开始
//首先定义结构体
type Product struct{
Code string `gorm:"column:code"`
Price uint `gorm:"column:price"`
}
//实现TableName方法返回表名即可
func(p Product)TableName()string {
return "product"
}
处理数据冲突
//以不处理为例
p :=&Product{Code:"D42",ID:1}
db.Clauses{clause.OnConflict{DoNothing:true}.Create(&p)}
使用默认值
//通过default标签
type User struct{
Id int64
Name string `gorm:"default:luc"`
Age int64 `gorm:"default:18"`
}
查询数据
//查询一条数据
u:=&User{}
db.First(u)
//查询多条数据
users:=make([]*User,0)
db.Where("name =?","jinzhu").Find(&useres)
db.Where(map[string]interface{}{"Name":"jinzhu","Age":18}).Find(users)
注意:
- 使用first时,需要注意查询不到数据会返回ErrRecordNotFound
- 使用Find查询多条数据,查询不到不会返回错误
- 使用结构体作为条件查询,Gorm只会查询非零字段,所以应该使用map来进行查询
更新数据
//条件更新单个列
db.Model(&User{ID:111}).Where("age > ?",18).Update("name","hello")
//更新多个列
db.Model(&User{ID:111}).Updates(User{Name:"hello",Age:18})
//根据map更新属性
db.Model(&User{ID:111}).Updates(map[string]interface{}{"name":"hello","Age":18})
//更新选定字段
db.Model(&User{ID:111}).Select("name").Updates(map[string]interface{}{"name":"hello","age":18})
//SQL表达式更新
db.Model(&User{ID:111}).Update("age",gorm.Expr("age*?+?",2,100))
删除数据
//物理删除
db.Delete(&User{},10) //删除id为10的记录(主键)
db.Delete(&User{}, "10") //删除id为10的记录(主键)
db.Delete(&User{}, []int[1,2,3}) //删除id为1,2,3的记录(主键)
db.Delete(&User{}, "name like ?","%jin%") //删除名字含jin的记录
db.Where("name like ?","%jinzhu%").Delete(&User{}) //删除名字含jin的记录
//软删除
//gorm提供了gorm.DeleteAt帮助用户实现软删除
//软删除只会把DeleteAt置为当前时间,并且无法通过正常方法查询到数据
//使用Unscoped可以查询到被软删的数据
事务
tx:=db.Begin() //开始事务
//执行db操作,用tx替换db
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()
return
}
//提交事务
tx.Commit()
//Transaction自动提交事务
if err := db.Transaction(func(tx *gorm.DB)error{
if err=tx.Create(&User{Name:"name"}).Error;err1=nil{
return err
}
if err=tx.Create(&User{name:"name1"}).Error;err!=nil{
tx.Rollback()
return err
}
return nil
}); err!=nil{
return
}
Hook
Hook是在创建、查询、更新、删除等操作之前、之后自动调用的函数
如果任何Hook返回错误,GORM将停止后续的操作并回滚事务
func (u *User)BeforeCreate(tx *gorm.DB)(err error){
if u.Age < 0{
return errors.New("can not save invalid data")
}
return
}
性能提高
- 对于写操作,为了确保数据的完整性,GORM将其封装在事务内运行,但这会降低性能,可以用
SkipDefaultTransaction关闭默认事务 - 使用
PrepareStmt缓存预编译语句可以提高后续调用速度
db,err:=gorm.Open(mysql.Open(dsn),
&gorm.Config{
SkipDefaultTransaction: true,
PrepareStmt: true,
})