Go框架Gorm|青训营笔记

63 阅读3分钟

image.png

这是我参与「第五届青训营 」笔记创作活动的的第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")
    }