返回顶部
首页 > 资讯 > 数据库 >Gorm—Go语言数据库框架
  • 573
分享到

Gorm—Go语言数据库框架

gorm框架数据库mysql 2023-08-18 22:08:30 573人浏览 安东尼
摘要

文章目录 一、GORM简介1、什么是Gorm?2、为什么选择GORM?3、如何使用GORM?4、约定大于配置大于编码GORM 默认使用ID作为表的主键GORM 默认使用结构体名的 snake case 复数作为表名临时指定表名gor


相关链接:
GORM中文官网: https://gorm.io/zh_CN/docs/
GoRM入门https://www.liwenzhou.com/posts/Go/gorm/
GORM增删改查CRUD: https://www.liwenzhou.com/posts/Go/gorm_crud/

一、GORM简介

1、什么是Gorm?

The fantastic ORM library for Golang aims to be developer friendly. ——官网

2、为什么选择GORM?

  • 全功能 ORM
  • 关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承)
  • Create,Save,Update,Delete,Find 中钩子方法
  • 支持 PreloadJoins 的预加载
  • 事务,嵌套事务,Save Point,Rollback To Saved Point
  • Context、预编译模式、DryRun 模式
  • 批量插入,FindInBatches,Find/Create with Map,使用 sql 表达式、Context Valuer 进行 CRUD
  • SQL 构建器,Upsert,数据库,Optimizer/Index/Comment Hint,命名参数,子查询
  • 复合主键,索引,约束
  • Auto Migration
  • 自定义 Logger
  • 灵活的可扩展插件 api:Database Resolver(多数据库,读写分离)、prometheus
  • 每个特性都经过了测试的重重考验
  • 开发者友好

3、如何使用GORM?

## 必须安装gormgo get -u gorm.io/gorm     ## 安装相应的数据库驱动。GORM 官方支持的数据库类型有: mysql, PostgreSQL, SQlite, SQL Servergo get -u gorm.io/driver/mysql  
  • 连接到MySQL数据库
package mainimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm""time")func main() {// 参考 https://GitHub.com/go-sql-driver/mysql#dsn-data-source-name 获取详情//dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"//db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})db, err := gorm.Open(mysql.New(mysql.Config{DSN:                       "root:123456@tcp(192.168.168.101:3306)/gorm?charset=utf8&parseTime=True&loc=Local", // DSN data source nameDefaultStringSize:         256,                        // string 类型字段的默认长度DisableDatetimePrecision:  true,                       // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持DontSupportRenameIndex:    true,                       // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引DontSupportRenameColumn:   true,                       // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列SkipInitializeWithVersion: false,                      // 根据当前 MySQL 版本自动配置}), &gorm.Config{})if err != nil {panic("failed to connect database")}// ----------------------------数据库连接池----------------------------sqlDB, err := db.DB()// SetMaxIdleConns 设置空闲连接池中连接的最大数量sqlDB.SetMaxIdleConns(10)// SetMaxOpenConns 设置打开数据库连接的最大数量。sqlDB.SetMaxOpenConns(100)// SetConnMaxLifetime 设置了连接可复用的最大时间。sqlDB.SetConnMaxLifetime(time.Hour)fmt.Println("success to link mysql")select {}}

4、约定大于配置大于编码

GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAtUpdatedAt 字段追踪创建、更新时间。

遵循 GORM 已有的约定,可以减少配置和代码量。如果约定不符合需求,GORM 允许自定义配置它们

GORM 默认使用ID作为表的主键

type User struct {     ID  string // 默认情况下,名为 `ID` 的字段会作为表的主键     Name string}

GORM 默认使用结构体名的 snake case 复数作为表名

eg:结构体 userinfo,其表名默认为user_infos

蛇形命名法(snake case)类似 驼峰命名法(camel case) ,都是要克服单词间的空格,从而把不同单词串连起来,最终达到创造出一种新的单词的效果。

临时指定表名

// 根据 User 的字段创建 `deleted_users` 表db.Table("deleted_users").AutoMigrate(&User{})// 从另一张表查询数据var deletedUsers []Userdb.Table("deleted_users").Find(&deletedUsers)// SELECT * FROM deleted_users;db.Table("deleted_users").Where("name = ?", "jinzhu").Delete(&User{})// DELETE FROM deleted_users WHERE name = 'jinzhu';

gorm.Model

GORM 定义一个 gorm.Model 结构体,其包括字段 IDCreatedAtUpdatedAtDeletedAt

// gorm.Model 的定义type Model struct {  ID        uint           `gorm:"primaryKey"`  CreatedAt time.Time  UpdatedAt time.Time  DeletedAt gorm.DeletedAt `gorm:"index"`}

tag标签【重点】

声明 model 时,tag 是可选的,GORM 支持以下 tag。 tag 名大小写不敏感,但建议使用驼峰 camelCase 命名风格。

标签名说明
column指定 db 表列名
type列数据类型,推荐使用兼容性好的通用类型
serializer指定如何序列化/反序列化到数据库, e.g: serializer:JSON/gob/unixtime
size指定列的数据大小/长度, e.g: size:256
primaryKey指定列作为主键
unique指定列唯一
default指定列为默认值
precision指定列的精度
scalespecifies column scale
not null指定列 NOT NULL
autoIncrement指定列为自增列
autoIncrementIncrementauto increment step, controls the interval between successive column values
embedded嵌入字段
embeddedPrefix嵌入字段的列名前缀
autoCreateTime记录创建时间
autoUpdateTime记录创建/更新时间
index根据选项创建索引
uniqueIndex唯一索引
check创建检查约束, eg: check:age > 13, refer Constraints
<-设置字段的写权限
<-:create create-only field,
<-:update update-only field,
<-:false no write permission,
<- create and update permission
->设置字段读权限
->:false no read permission
-忽略当前字段
- no read/write permission,
-:migration no migrate permission,
-:all no read/write/migrate permission
comment【迁移时】为字段添加注释

高级选项

字段权限

可导出的字段在使用 GORM 进行 CRUD 时拥有全部的权限,此外,GORM 允许用标签控制字段级别的权限。这样就可以让一个字段的权限是只读、只写、只创建、只更新或者被忽略。

type User struct {  Name string `gorm:"<-:create"` // allow read and create  Name string `gorm:"<-:update"` // allow read and update  Name string `gorm:"<-"`        // allow read and write (create and update)  Name string `gorm:"<-:false"`  // allow read, disable write permission  Name string `gorm:"->"`        // readonly (disable write permission unless it configured)  Name string `gorm:"->;<-:create"` // allow read and create  Name string `gorm:"->:false;<-:create"` // createonly (disabled read from db)  Name string `gorm:"-"`            // ignore this field when write and read with struct  Name string `gorm:"-:all"`        // ignore this field when write, read and migrate with struct  Name string `gorm:"-:migration"`  // ignore this field when migrate with struct}
创建、更新时间

GORM 约定使用 CreatedAtUpdatedAt 追踪创建/更新时间。如果定义了这种字段,GORM 在创建、更新时会自动填充当前时间。

要使用不同名称的字段,可以配置 autoCreateTimeautoUpdateTime 标签。

type User struct {  CreatedAt time.Time // 在创建时,如果该字段值为零值,则使用当前时间填充  UpdatedAt int       // 在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充  Updated   int64 `gorm:"autoUpdateTime:nano"` // 使用时间戳填纳秒数充更新时间  Updated   int64 `gorm:"autoUpdateTime:milli"` // 使用时间戳毫秒数填充更新时间  Created   int64 `gorm:"autoCreateTime"`      // 使用时间戳秒数填充创建时间}
嵌入结构体

可以通过标签 embedded 将一个结构体嵌入另一个结构体。可以使用标签 embeddedPrefix 来为 db 中的字段名添加前缀。

type Author struct {    Name  string    Email string}type Blog struct {  ID      int  Author  Author `gorm:"embedded;embeddedPrefix:author_"`  Upvotes int32}// 等效于type Blog struct {  ID          int64    AuthorName  string    AuthorEmail string  Upvotes     int32}

二、CRUD

Gorm增删改查CRUD最常用到的语法。

1、增[Create]

创建单条记录

// -----------------------------插入单条记录---------------------------------user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}result := db.Create(&user) // 通过数据的指针来创建user.ID             // 返回插入数据的主键result.Error        // 返回 errorresult.RowsAffected // 返回插入记录的条数// 创建记录并更新给出的字段db.Select("Name", "Age", "CreatedAt").Create(&user)// INSERT INTO `users` (`name`,`age`,`created_at`) VALUES ("jinzhu", 18, "2020-07-04 11:05:21.775")

创建批量记录

// -----------------------------批量插入多条记录-----------------------------//要有效地插入大量记录,请将一个 slice 传递给 Create 方法。 GORM 将生成单独一条SQL语句来插入所有数据,并回填主键的值,钩子方法也会被调用。var users = []User{{Name: "jinzhu1"}, {Name: "jinzhu2"}, {Name: "jinzhu3"}}db.Create(&users)//使用 CreateInBatches 分批创建时,你可以指定每批的数量。var users = []User{{name: "jinzhu_1"}, ...., {Name: "jinzhu_10000"}}// 数量为 100db.CreateInBatches(users, 100)

创建hook【创建钩子】

GORM 允许用户定义的钩子有 BeforeSave, BeforeCreate, AfterSave, AfterCreate 创建记录时将调用这些钩子方法。

func (u *User) BeforeCreate(tx *gorm.DB) (err error) {  u.UUID = uuid.New()    if u.Role == "admin" {        return errors.New("invalid role")    }    return}// 如果想跳过 钩子 方法,可以使用 SkipHooks 会话模式DB.Session(&gorm.Session{SkipHooks: true}).Create(&user)DB.Session(&gorm.Session{SkipHooks: true}).Create(&users)DB.Session(&gorm.Session{SkipHooks: true}).CreateInBatches(users, 100)

支持Map创建

db.Model(&User{}).Create(map[string]interface{}{  "Name": "jinzhu", "Age": 18,})// batch insert from `[]map[string]interface{}{}`db.Model(&User{}).Create([]map[string]interface{}{  {"Name": "jinzhu_1", "Age": 18},  {"Name": "jinzhu_2", "Age": 20},})

默认值

对于声明了默认值的字段,像 0''false 等零值是不会保存到数据库。需要使用指针类。

type User struct {  gorm.Model  Name string         `gorm:"default:xiaoming"`  Age  *int           `gorm:"default:18"`  Active sql.NullBool `gorm:"default:true"`}type User struct {  ID        string `gorm:"default:uuid_generate_v3()"` // db func  FirstName string  LastName  string  Age       uint8  FullName  string `gorm:"->;type:GENERATED ALWAYS AS (concat(firstname,' ',lastname));default:(-);"`}

2、查[Retrieve]

查询指定记录

GORM 提供了 FirstTakeLast 方法,以便从数据库中检索单个对象。当查询数据库时它添加了 LIMIT 1 条件,且没有找到记录时,它会返回 ErrRecordNotFound 错误。

如果想避免ErrRecordNotFound错误,可以使用Find,比如db.Limit(1).Find(&user)Find方法可以接受struct和slice的数据。

// 获取第一条记录(主键升序)。只有在目标 struct 是指针或者通过 db.Model() 指定 model 时,该方法才有效。db.First(&user)// SELECT * FROM users ORDER BY id LIMIT 1;// 获取一条记录,没有指定排序字段db.Take(&user)// SELECT * FROM users LIMIT 1;// 获取最后一条记录(主键降序)db.Last(&user)// SELECT * FROM users ORDER BY id DESC LIMIT 1;result := db.First(&user)result.RowsAffected // 返回找到的记录数result.Error        // returns error or nil// 检查 ErrRecordNotFound 错误errors.Is(result.Error, gorm.ErrRecordNotFound)

主键索引查询

db.First(&user, 10)// SELECT * FROM users WHERE id = 10;db.First(&user, "10")// SELECT * FROM users WHERE id = 10;db.Find(&users, []int{1,2,3})// SELECT * FROM users WHERE id IN (1,2,3);db.First(&user, "id = ?", "1b74413f-f3b8-409f-ac47-e8c062e3472a")// SELECT * FROM users WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a";

查询全部记录

// Get all recordsresult := db.Find(&users)// SELECT * FROM users;result.RowsAffected // returns found records count, equals `len(users)`result.Error        // returns error

查询hook【查询钩子】

// -----------------------------代码示例-------------------------func (u *User) AfterFind(tx *gorm.DB) (err error) {  if u.MemberShip == "" {    u.MemberShip = "user"  }  return}

条件【重点】

//-----------------------------string条件-------------------------// Get first matched recorddb.Where("name = ?", "jinzhu").First(&user)// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;// Get all matched recordsdb.Where("name <> ?", "jinzhu").Find(&users)// SELECT * FROM users WHERE name <> 'jinzhu';// INdb.Where("name IN ?", []string{"jinzhu", "jinzhu 2"}).Find(&users)// SELECT * FROM users WHERE name IN ('jinzhu','jinzhu 2');// LIKEdb.Where("name LIKE ?", "%jin%").Find(&users)// SELECT * FROM users WHERE name LIKE '%jin%';// ANDdb.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;// Timedb.Where("updated_at > ?", lastWeek).Find(&users)// SELECT * FROM users WHERE updated_at > '2000-01-01 00:00:00';// BETWEENdb.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)// SELECT * FROM users WHERE created_at BETWEEN '2000-01-01 00:00:00' AND '2000-01-08 00:00:00';//-----------------------------筛选特定字段-------------------------db.Select("name", "age").Find(&users)// SELECT name, age FROM users;db.Select([]string{"name", "age"}).Find(&users)// SELECT name, age FROM users;db.Table("users").Select("COALESCE(age,?)", 42).Rows()// SELECT COALESCE(age,'42') FROM users;//-----------------------------Struct & Map 条件-------------------------// Structdb.Where(&User{Name: "jinzhu", Age: 20}).First(&user)// SELECT * FROM users WHERE name = "jinzhu" AND age = 20 ORDER BY id LIMIT 1;// Mapdb.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)// SELECT * FROM users WHERE name = "jinzhu" AND age = 20;// Slice of primary keysdb.Where([]int64{20, 21, 22}).Find(&users)// SELECT * FROM users WHERE id IN (20, 21, 22);//-----------------------------内联条件-------------------------// Get by primary key if it were a non-integer typedb.First(&user, "id = ?", "string_primary_key")// SELECT * FROM users WHERE id = 'string_primary_key';// Plain SQLdb.Find(&user, "name = ?", "jinzhu")// SELECT * FROM users WHERE name = "jinzhu";db.Find(&users, "name <> ? AND age > ?", "jinzhu", 20)// SELECT * FROM users WHERE name <> "jinzhu" AND age > 20;// Structdb.Find(&users, User{Age: 20})// SELECT * FROM users WHERE age = 20;// Mapdb.Find(&users, map[string]interface{}{"age": 20})// SELECT * FROM users WHERE age = 20;//-----------------------------Not条件-------------------------db.Not("name = ?", "jinzhu").First(&user)// SELECT * FROM users WHERE NOT name = "jinzhu" ORDER BY id LIMIT 1;// Not Indb.Not(map[string]interface{}{"name": []string{"jinzhu", "jinzhu 2"}}).Find(&users)// SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2");// Structdb.Not(User{Name: "jinzhu", Age: 18}).First(&user)// SELECT * FROM users WHERE name <> "jinzhu" AND age <> 18 ORDER BY id LIMIT 1;// Not In slice of primary keysdb.Not([]int64{1,2,3}).First(&user)// SELECT * FROM users WHERE id NOT IN (1,2,3) ORDER BY id LIMIT 1;//-----------------------------Or条件-------------------------db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)// SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin';// Structdb.Where("name = 'jinzhu'").Or(User{Name: "jinzhu 2", Age: 18}).Find(&users)// SELECT * FROM users WHERE name = 'jinzhu' OR (name = 'jinzhu 2' AND age = 18);// Mapdb.Where("name = 'jinzhu'").Or(map[string]interface{}{"name": "jinzhu 2", "age": 18}).Find(&users)// SELECT * FROM users WHERE name = 'jinzhu' OR (name = 'jinzhu 2' AND age = 18);//-----------------------------Order排序-------------------------db.Order("age desc, name").Find(&users)// SELECT * FROM users ORDER BY age desc, name;// Multiple ordersdb.Order("age desc").Order("name").Find(&users)// SELECT * FROM users ORDER BY age desc, name;db.Clauses(clause.OrderBy{  Expression: clause.Expr{SQL: "FIELD(id,?)", Vars: []interface{}{[]int{1, 2, 3}}, WithoutParentheses: true},}).Find(&User{})// SELECT * FROM users ORDER BY FIELD(id,1,2,3)//-----------------------------Limit和Offset-------------------------db.Limit(3).Find(&users)// SELECT * FROM users LIMIT 3;// Cancel limit condition with -1db.Limit(10).Find(&users1).Limit(-1).Find(&users2)// SELECT * FROM users LIMIT 10; (users1)// SELECT * FROM users; (users2)db.Offset(3).Find(&users)// SELECT * FROM users OFFSET 3;db.Limit(10).Offset(5).Find(&users)// SELECT * FROM users OFFSET 5 LIMIT 10; // 分页// Cancel offset condition with -1db.Offset(10).Find(&users1).Offset(-1).Find(&users2)// SELECT * FROM users OFFSET 10; (users1)// SELECT * FROM users; (users2)//-----------------------------Group by和Having-------------------------db.Model(&User{}).Select("name, sum(age) as total").Where("name LIKE ?", "group%").Group("name").First(&result)// SELECT name, sum(age) as total FROM `users` WHERE name LIKE "group%" GROUP BY `name` LIMIT 1db.Model(&User{}).Select("name, sum(age) as total").Group("name").Having("name = ?", "group").Find(&result)// SELECT name, sum(age) as total FROM `users` GROUP BY `name` HAVING name = "group"//-----------------------------Distinct-------------------------db.Distinct("name", "age").Order("name, age desc").Find(&results)//-----------------------------Scan-------------------------//Scanning results into a struct works similarly to the way we use Findtype Result struct {  Name string  Age  int}var result Resultdb.Table("users").Select("name", "age").Where("name = ?", "AntoNIO").Scan(&result)// Raw SQLdb.Raw("SELECT name, age FROM users WHERE name = ?", "Antonio").Scan(&result)

3、改[Update]

更新指定记录

//-----------------------------保存所有字段-------------------------db.First(&user)user.Name = "jinzhu 2"user.Age = 100db.Save(&user)// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111;//-----------------------------更新单个列-------------------------// 条件更新db.Model(&User{}).Where("active = ?", true).Update("name", "hello")// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE active=true;// User 的 ID 是 `111`db.Model(&user).Update("name", "hello")// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;// 根据条件和 model 的值进行更新db.Model(&user).Where("active = ?", true).Update("name", "hello")// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;//-----------------------------更新多列-------------------------// 根据 `struct` 更新属性,只会更新非零值的字段db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;// 根据 `map` 更新属性db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})// UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;//-----------------------------更新选定字段-------------------------// 使用 Map 进行 Select// User's ID is `111`:db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})// UPDATE users SET name='hello' WHERE id=111;db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})// UPDATE users SET age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;// 使用 Struct 进行 Select(会 select 零值的字段)db.Model(&user).Select("Name", "Age").Updates(User{Name: "new_name", Age: 0})// UPDATE users SET name='new_name', age=0 WHERE id=111;// Select 所有字段(查询包括零值字段的所有字段)db.Model(&user).Select("*").Update(User{Name: "jinzhu", Role: "admin", Age: 0})// Select 除 Role 外的所有字段(包括零值字段的所有字段)db.Model(&user).Select("*").Omit("Role").Update(User{Name: "jinzhu", Role: "admin", Age: 0})

更新批量记录

//-----------------------------批量更新-------------------------// 根据 struct 更新db.Model(User{}).Where("role = ?", "admin").Updates(User{Name: "hello", Age: 18})// UPDATE users SET name='hello', age=18 WHERE role = 'admin';// 根据 map 更新db.Table("users").Where("id IN ?", []int{10, 11}).Updates(map[string]interface{}{"name": "hello", "age": 18})// UPDATE users SET name='hello', age=18 WHERE id IN (10, 11);//-----------------------------禁止全局更新-------------------------//如果在没有任何条件的情况下执行批量更新,默认情况下,GORM 不会执行该操作,并返回 ErrMissingWhereClause 错误。对此,必须加一些条件,或者使用原生 SQL,或者启用 AllowGlobalUpdate 模式db.Model(&User{}).Update("name", "jinzhu").Error // gorm.ErrMissingWhereClausedb.Model(&User{}).Where("1 = 1").Update("name", "jinzhu")// UPDATE users SET `name` = "jinzhu" WHERE 1=1db.Exec("UPDATE users SET name = ?", "jinzhu")// UPDATE users SET name = "jinzhu"db.Session(&gorm.Session{AllowGlobalUpdate: true}).Model(&User{}).Update("name", "jinzhu")// UPDATE users SET `name` = "jinzhu"//-----------------------------更新记录数-------------------------// 通过 `RowsAffected` 得到更新的记录数result := db.Model(User{}).Where("role = ?", "admin").Updates(User{Name: "hello", Age: 18})// UPDATE users SET name='hello', age=18 WHERE role = 'admin';result.RowsAffected // 更新的记录数result.Error        // 更新的错误

更新hook【更新钩子】

//-----------------------------更新 Hook-------------------------//GORM 支持 BeforeSave、BeforeUpdate、AfterSave、AfterUpdate 钩子,这些方法将在更新记录时被调用func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {    if u.Role == "admin" {        return errors.New("admin user not allowed to update")    }    return}

4、删[Delete]

删除指定记录

//-----------------------------删除一条记录-------------------------//删除一条记录时,删除对象需要指定主键,否则会触发 批量 Delete// Email 的 ID 是 `10`db.Delete(&email)// DELETE from emails where id = 10;// 带额外条件的删除db.Where("name = ?", "jinzhu").Delete(&email)// DELETE from emails where id = 10 AND name = "jinzhu";//-----------------------------根据主键删除-------------------------db.Delete(&User{}, 10)// DELETE FROM users WHERE id = 10;db.Delete(&User{}, "10")// DELETE FROM users WHERE id = 10;db.Delete(&users, []int{1,2,3})// DELETE FROM users WHERE id IN (1,2,3);

删除批量记录

//-----------------------------批量删除-------------------------db.Where("email LIKE ?", "%jinzhu%").Delete(&Email{})// DELETE from emails where email LIKE "%jinzhu%";db.Delete(&Email{}, "email LIKE ?", "%jinzhu%")// DELETE from emails where email LIKE "%jinzhu%";//-----------------------------禁止全局删除-------------------------//如果在没有任何条件的情况下执行批量删除,GORM 不会执行该操作,并返回 ErrMissingWhereClause 错误。对此,你必须加一些条件,或者使用原生 SQL,或者启用 AllowGlobalUpdate 模式db.Delete(&User{}).Error // gorm.ErrMissingWhereClausedb.Where("1 = 1").Delete(&User{})// DELETE FROM `users` WHERE 1=1db.Exec("DELETE FROM users")// DELETE FROM usersdb.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&User{})// DELETE FROM users

软删除【重点】

如果model包含gorm.deleted_at 字段(gorm.Model 已经包含了该字段),它将自动获得软删除的能力!拥有软删除能力的模型调用 Delete 时,记录不会从数据库中被真正删除。GORM 会将 DeletedAt 置为当前时间,并且不能再通过普通的查询方法找到该记录

//-----------------------------软删除-------------------------//By default, gorm.Model uses *time.Time as the value for the DeletedAt field, and it provides other data formats support with plugin gorm.io/plugin/soft_deleteimport "gorm.io/plugin/soft_delete"type User struct {  ID        uint  Name      string                `gorm:"uniqueIndex:udx_name"`  DeletedAt soft_delete.DeletedAt `gorm:"uniqueIndex:udx_name"`  // DeletedAt soft_delete.DeletedAt `gorm:"softDelete:nano"`  //IsDel soft_delete.DeletedAt `gorm:"softDelete:flag"`}// QuerySELECT * FROM users WHERE is_del = 0;// DeleteUPDATE users SET is_del = 1 WHERE ID = 1;// user 的 ID 是 `111`db.Delete(&user)// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;// 批量删除db.Where("age = ?", 20).Delete(&User{})// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;// 在查询时会忽略被软删除的记录db.Where("age = 20").Find(&user)// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;//-----------------------------查找被软删除的记录-------------------------db.Unscoped().Where("age = 20").Find(&users)// SELECT * FROM users WHERE age = 20;//-----------------------------永久删除-------------------------db.Unscoped().Delete(&order)// DELETE FROM orders WHERE id=10;

删除hook【删除钩子】

//-----------------------------删除 Hook-------------------------func (u *User) BeforeDelete(tx *gorm.DB) (err error) {    if u.Role == "admin" {        return errors.New("admin user not allowed to delete")    }    return}

5、原生sql

原生查询 SQL

//-----------------------------原生查询 SQL 和 Scan-------------------------type Result struct {  ID   int  Name string  Age  int}var result Resultdb.Raw("SELECT id, name, age FROM users WHERE name = ?", 3).Scan(&result)db.Raw("SELECT id, name, age FROM users WHERE name = ?", 3).Scan(&result)var age intdb.Raw("SELECT SUM(age) FROM users WHERE role = ?", "admin").Scan(&age)var users []Userdb.Raw("UPDATE users SET name = ? WHERE age = ? RETURNING id, name", "jinzhu", 20).Scan(&users)

原生 Exec SQL

//-----------------------------Exec 原生 SQL-------------------------db.Exec("DROP TABLE users")db.Exec("UPDATE orders SET shipped_at = ? WHERE id IN ?", time.Now(), []int64{1, 2, 3})// Exec with SQL Expressiondb.Exec("UPDATE users SET money = ? WHERE name = ?", gorm.Expr("money * ? + ?", 10000, 1), "jinzhu")

Row和Rows

//获取 *sql.Row 结果// 使用 GORM API 构建 SQLrow := db.Table("users").Where("name = ?", "jinzhu").Select("name", "age").Row()row.Scan(&name, &age)// 使用原生 SQLrow := db.Raw("select name, age, email from users where name = ?", "jinzhu").Row()row.Scan(&name, &age, &email)// 原生 SQLrows, err := db.Raw("select name, age, email from users where name = ?", "jinzhu").Rows()defer rows.Close()for rows.Next() {  rows.Scan(&name, &age, &email)  // 业务逻辑...}rows, err := db.Model(&User{}).Where("name = ?", "jinzhu").Select("name, age, email").Rows() // (*sql.Rows, error)defer rows.Close()var user Userfor rows.Next() {  // ScanRows 将一行扫描至 user  db.ScanRows(rows, &user)  // 业务逻辑...}

来源地址:https://blog.csdn.net/qq_41822345/article/details/126072106

您可能感兴趣的文档:

--结束END--

本文标题: Gorm—Go语言数据库框架

本文链接: https://www.lsjlt.com/news/374835.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Gorm—Go语言数据库框架
    文章目录 一、GORM简介1、什么是Gorm?2、为什么选择GORM?3、如何使用GORM?4、约定大于配置大于编码GORM 默认使用ID作为表的主键GORM 默认使用结构体名的 snake case 复数作为表名临时指定表名gor...
    99+
    2023-08-18
    gorm框架 数据库 mysql
  • Go入门之Gorm 框架
    Gorm框架 Gorm简介Gorm连接数据库Gorm进行数据库基本操作Gorm 对数据库进行CURD事物Transaction Gorm简介 gorm是Golang语言中一款性能极好的...
    99+
    2023-08-31
    数据库 mysql golang
  • Go语言使用GORM操作数据库使用指南
    目录简介安装 GORM连接到数据库定义模型自动迁移基本 CRUD 操作插入记录查询记录更新记录删除记录详细api详解1. 查询2. 插入3. 更新4. 删除总结简介 GORM(全称为...
    99+
    2023-05-20
    Go语言 GORM操作数据库 Go语言 操作数据库 Go GORM 数据库 Go语言 GORM
  • 大数据处理新选择:Go语言+Numpy库+Laravel框架
    大数据处理新选择:Go语言 Numpy库 Laravel框架 随着信息化时代的到来,数据越来越成为企业和个人决策的重要依据,数据量的急剧增长也使得大数据处理成为一项重要的技术。为了更高效地处理大数据,需要选择一种高效的编程语言和相应的库或框...
    99+
    2023-08-10
    numpy 大数据 laravel
  • 搭建Go语言的ORM框架Gorm的具体步骤(从Java到go)
    目录【提问】【解答】1、检查Go的安装2、安装Gorm3、安装对应数据库的驱动4、编写「数据库连接」代码5、编写「数据Model」代码6、编写「数据查询」代码【提问】 如何使用Gol...
    99+
    2024-04-02
  • golang gorm框架数据库的连接操作示例
    目录1. 连接数据库1.1 MySQL1.2 PostgreSQL1.3 Sqlite31.4 不支持的数据库2. 迁移2.1. 自动迁移2.2. 检查表是否存在2.3. 创建表2....
    99+
    2024-04-02
  • Go语言、Numpy库、Laravel框架:谁才是大数据处理的王者?
    在当今的数据时代,大数据处理成为了一个热门话题。而在大数据处理中,Go语言、Numpy库、Laravel框架都是备受关注的工具。那么,它们之间到底谁是大数据处理的王者呢?下面就让我们来一起探讨一下。 一、Go语言 Go语言是谷歌公司开发的一...
    99+
    2023-08-10
    numpy 大数据 laravel
  • go语言框架有哪些
    go语言框架有“Gin”、“Beego”、“Echo”、“Gorilla”和“Iris”五种:1、Gin,一个快速的 Web 框架,提供了快速的路由和中间件支持;2、Beego,一个全功能的 MVC 框架,被设计为快速开发Web应用程序;3...
    99+
    2023-12-12
    go语言
  • Go语言中GORM存取数组/自定义类型数据
    目录GORM存取数组类型数据一、GORM的自定义类型1. Scanner/Valuer接口2. 数组变量3. 测试二、实际生产​总结GORM存取数组类型数据 在GORM不支持数组类型...
    99+
    2023-01-17
    Gorm 数组字段处理 gorm 数组 gorm 自定义类型
  • Go语言中使用Spring框架的函数?
    在Go语言中,使用Spring框架的函数并不是一个常见的操作,因为Spring框架通常用于Java语言中。但是,有些开发者可能希望在Go语言中使用Spring框架的一些函数,以便在项目中更好地管理依赖关系和控制反转。 首先,我们需要理解Sp...
    99+
    2023-11-05
    spring 框架 函数
  • go语言rpc框架有哪些
    go语言rpc框架有:1、Go RPC,go语言标准库中自带的框架,提供了简单方便的RPC方法调用;2、gRPC,由谷歌开发的框架,可以生成多种不同语言的RPC客户端和服务器端代码;3、Micro,基于Go语言的微服务框架,提供了一个强大的...
    99+
    2023-07-31
  • go语言web框架有哪些
    go语言web框架有Gin、Echo、Beego、Revel、Iris框架等。详细介绍:1、Gin框架具有高性能和低内存占用的特点,适用于中小型Web应用的开发;2、Echo框架具有高性能、简单易用的特点,使用了高性能的HTTP路由器,支持...
    99+
    2023-07-31
  • 你知道哪些Go语言中的数据类型框架?
    Go语言作为一门现代化的编程语言,其数据类型框架也是非常丰富和实用的。在本篇文章中,我们将会介绍Go语言中的一些常用的数据类型框架,以及它们在实际应用中的使用方法和优缺点。 一、数组 数组是Go语言中最基本的数据类型之一。它是由一系列相同数...
    99+
    2023-07-03
    数据类型 npm 框架
  • GO语言中有哪些优秀的数据类型框架?
    在GO语言中,数据类型框架是非常重要的。这些框架可以帮助我们更好地管理和操作数据,提高代码的可读性和可维护性。在本文中,我们将介绍一些优秀的GO语言数据类型框架,以及它们的优点和缺点。 GORM GORM是一个非常流行的GO语言ORM...
    99+
    2023-07-03
    数据类型 框架 git
  • Go语言中有哪些数据类型框架值得一试?
    Go语言是一种现代化的编程语言,它在数据类型方面提供了很多选择。在本文中,我们将介绍一些值得一试的数据类型框架,其中包括基本数据类型以及一些高级数据类型。 基本数据类型: int int是Go语言中最基本的数据类型之一,它表示整数类型。它...
    99+
    2023-07-03
    数据类型 npm 框架
  • 探究Go语言框架:了解五款必备框架!
    深入解析Go语言框架:你需要了解的五个框架! 随着Go语言的不断发展和流行,越来越多的开发者开始选择Go语言作为他们的开发语言。为了更高效地开发和部署应用程序,开发者们经常会选择使用框...
    99+
    2024-02-26
    框架 go语言 深入
  • go语言中web框架是什么
    这篇文章将为大家详细讲解有关go语言中web框架是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。基于go语言的web框架:1、Beego,开源的高性能Go语言Web框架;2、Iris,快速、简单但功能...
    99+
    2023-06-14
  • go语言中的框架有哪些
    go语言中的框架有哪些?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。操作环境:windows10系统、GO 1.11.2、thinkpad t480电脑。Go 是一个快速增...
    99+
    2023-06-14
  • go语言有微服务框架吗
    go语言有微服务框架,例如:1、Istio,是一个开源的微服务管理、保护和监控框架;2、Go-kit,是一个Go语言的分布式开发包,用于开发微服务;3、Go-zero,是一个集成了各种工程实践的web和rpc框架;4、Go-micro,是一...
    99+
    2023-05-14
    微服务框架 go语言 Golang Go
  • go语言的web框架有哪些
    go语言有Gin、Beego、Revel、Echo和Iris等web框架。1、Gin,提供一种轻量级框架,具备高性能和易用性;2、Beego,提供一种简单、高效、可扩展的开发体验,具有良好的性能;3、Revel,提供一种简单、高效、可扩展的...
    99+
    2023-07-31
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作