这是我参与「第五届青训营 」笔记创作活动的的第5天
本文导航:
- 基本使用
- import引入grom包
- 数据库
- 结构体
- 创建表
- 创建数据
- 查询数据
- 更新数据
- 事务
- Hook
- 性能提高
基本使用
- Gorm使用名为ID的字段作为主键
- 使用结构体的蛇形负数作为表名
- 字段名的蛇形作为列名
- 使用CreatedAt、UpdatedAt字段作为创建、更新时间
import引入grom包
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
数据库
- GORM目前支持MySQL、SQLServer、PostgreSQL、SQLite.
- GORM通过驱动来连接数据库,如果需要连接其它类型的数据库,可以复用/自行开发驱动。
dsn := "root:root@tcp(127.0.0.1:3306)/test1?charset=utf8mb4&parseTime=True&loc=Local"
//模板username:password@@tcp(127.0.0.1:3306)/db_name?charset=utf8mb4&parseTime=True&loc=Local
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
结构体
type User struct {
gorm.Model//默认的结构体
Code string
Price uint
}
// gorm.Model 定义
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
创建表
db.CreateTable(&User{}) //创建表名users,默认复数作为表名
db.AutoMigrate(&User{}) //createtable提高版,可以修改已经存在的表,更新结构体
创建数据
- 创建一条数据
p:=&User{Code:"D42"}
res:=db.Create(p)
- 创建多条数据
user:=[]*User{{Code:"41"},{Code:"D42"},{Code:"D43"}}
res=db.Create(user)
查询数据
- 查询一条数据
db.First(&user, "code = ?", "D42") //select*from users where code="D42" 查找 code 字段值为 D42 的记录
-
查询多条数据
user:=make([]*User,0) result:=db.Where("code>10").Find(&user)//select*from users where code>10 fmt.Println(result.RowsAffected)//返回找到的记录数 fmt.Println(result.Error)//返回错误
-
tips:使用First时,需要注意查询不到数据会返回ErrRecordNotFound。 使用Find查询多条数据,查询不到数据不会返回错误。
-
当使用结构体作为条件查询时,GORM只会查询非零值字段。这意味着如果您的字段值为0、"、false或其他零值,该字段不会被用于构建查询条件,使用Map来构建查询条件。
// Struct db.Find(&users, User{Code: 42}) SELECT * FROM users WHERE code = 42; // Map db.Find(&users, map[string]interface{}{"code": 42}) SELECT * FROM users WHERE code = 42;
更新数据
- 一个字段
// Update - 将 user 的 price 更新为 200
db.Model(&user).Update("Price", 200)
- 多个字段
// Update - 更新多个字段
db.Model(&user).Updates(User{Price: 200, Code: "F42"}) // 仅更新非零值字段
db.Model(&user).Updates(map[string]interface{}{"Price": 200, "Code": "F42"})
删除数据
- 物理删除:直接把数据从数据库中删除
db.Delete(&user, 1)//delete from users where id=1
- 软删除
u:=User{ID:1}
db.delete(&u)//update users set deleted_at="xxx xxx xxx"where id=1
users := make([]*User,0)
//在查询时会忽略被软删除的记录
db.wWhere( query: "code = 20").Find(&users)// SELECT * FRON users WHERE code = 42 AMD deleted_at IS NULL;
//在查询时不会忽略被软删除的记录
db.Unscoped().where( query: "code = 20").Find(&users)// SELECT * FROM users WHERE code = 42;
事务
Gorm提供了Begin、Commit、Rollback方法用于使用事务
// Delete - 删除 user
db.Delete(&user, 1)
tx := db.Begin() //开始事务
//在事务中执行一些db 操作(从这里开始,您应该使用‘tx’而不是 'db ' )
if err = tx.Create(&User{Code: "code"}).Error; err != nil {
tx.Rollback()
//遇到错误时回滚事务
return
}
if err = tx.Create(&User{Code: "code1"}).Error; err != nil {
tx.Rollback()
return
}
//提交事务
tx.commit()
Gorm提供了Tansaction方法用于自动提交事务,避免用户漏写Commit、Rollbcak。
if err = db.Transaction(func(tx *gorm.DB) error {
if err = tx.Create(&User{Code: "code"}).Error; err != nil{
return err
}
if err = tx.Create(&User{Code: "code1"}).Error; err != nil {
tx.Rollback()
return err
}
return nil
}); err!=nil{
return
}
Hook
是在创建、查询、更新、删除等操作之前、之后自动调用的函数。如果任何Hook返回错误,GORM将停止后续的操作并回滚事务。
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
if u.Age < 0 {
return errors.New( text: "can't save invalid data")
}
return
}
func (u *User) AfterCreate(tx*gorm.DB)(err error){
return tx.Create(&Email{ID: u.ID,Email: u.Name + "@*** .com"}).Error
}
提高性能
- 对于写操作(创建、更新、删除),为了确保数据的完整性,GORM会将它们封装在事务内运行。但这会降低性能,你可以使用SkipDefaultTransaction关闭默认事务。
- 使用PrepareStmt 缓存预编译语句可以提高后续调用的速度。
db,err := gonm.Open(mysql.Open(dsn: "username:password@tcp(localhost:9910)/database?charset=utf8"),
gorm. Config{
SkipDefaultTransaction: true,//关闭默认事务PrepareStmt:
PrepareStmt: true},//缓存预编译语句
)
if err != nil {
panic( "failed to connect database")
}