快速入门GORM,使用GORM进行CURD

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 1.模型使用约定:GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间GORM 定义一个 gorm.Model 结构体,其包括字段 ID、CreatedAt、UpdatedAt、DeletedAt


1.模型使用


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


GORM 定义一个 gorm.Model 结构体,其包括字段 ID、CreatedAt、UpdatedAt、DeletedAt


type Model struct {
  ID        uint `gorm:"primarykey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt DeletedAt `gorm:"index"`
}


建表实例:


package main
import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
// 数据表
type UserInfo struct {
  ID    int64
  Name  string
  Hobby string
}
func main() {
  dsn := "root:root@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
  db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
  db.AutoMigrate(&UserInfo{}) // 生成表结构
}


2.创建表记录


普通的创建:


package main
import (
  "fmt"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
// 数据表
type UserInfo struct {
  ID    int64
  Name  string
  Hobby string
}
func main() {
  dsn := "root:root@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
  db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
  userInfo := UserInfo{Name: "dahe", Hobby: "Go语言"}
  result := db.Create(&userInfo)
  fmt.Println(result.RowsAffected) // 返回插入记录的条数
  if result.Error == nil {         // 检测error
    fmt.Println("no errors!!!")
  }
}


批量插入:

要有效地插入大量记录,请将一个 slice 传递给 Create 方法。 GORM 将生成单独一条SQL语句来插入所有数据,并回填主键的值,钩子方法也会被调用。


package main
import (
  "fmt"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
// 数据表
type UserInfo struct {
  ID    int64
  Name  string
  Hobby string
}
func main() {
  dsn := "root:root@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
  db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
  var userInfo = []UserInfo{{Name: "qianyue"}, {Name: "王伟"}, {Name: "李四"}}
  result := db.Create(&userInfo)
  fmt.Println(result.RowsAffected) // 返回插入记录的条数
  if result.Error == nil {         // 检测error
    fmt.Println("no errors!!!")
  }
}


使用 CreateInBatches 分批创建时,你可以指定每批的数量,例如:


// 数量为 100
db.CreateInBatches(users, 100)


3.查询记录


检索单个对象


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


package main
import (
  "fmt"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
// 数据表
type UserInfo struct {
  ID    int64
  Name  string
  Hobby string
}
func main() {
  dsn := "root:root@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
  db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
  var userInfo UserInfo
  result := db.First(&userInfo)   // 查询表的第一行
  fmt.Println(userInfo)           // 输出查询的结果
  fmt.Println(result.RowsAffected) // 返回插入记录的条数
  if result.Error == nil {         // 检测error
    fmt.Println("no errors!!!")
  }
}


// 获取第一条记录(主键升序)
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)


First 和 Last 会根据主键排序,分别查询第一条和最后一条记录。 只有在目标 struct 是指针或者通过db.Model() 指定 model 时,该方法才有效。 此外,如果相关 model 没有定义主键,那么将按 model的第一个字段进行排序。


用主键检索


如果主键是数字类型,您可以使用 内联条件 来检索对象。 传入字符串参数时,需要特别注意 SQL 注入问题


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);


如果主键是字符串(例如像 uuid),查询将被写成这样:


db.First(&user, "id = ?", "1b74413f-f3b8-409f-ac47-e8c062e3472a")
// SELECT * FROM users WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a";


检索全部对象


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


条件


string条件:


// Get first matched record
db.Where("name = ?", "jinzhu").First(&user)
// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
// Get all matched records
db.Where("name <> ?", "jinzhu").Find(&users)
// SELECT * FROM users WHERE name <> 'jinzhu';
// IN
db.Where("name IN ?", []string{"jinzhu", "jinzhu 2"}).Find(&users)
// SELECT * FROM users WHERE name IN ('jinzhu','jinzhu 2');
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
// SELECT * FROM users WHERE name LIKE '%jin%';
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
// Time
db.Where("updated_at > ?", lastWeek).Find(&users)
// SELECT * FROM users WHERE updated_at > '2000-01-01 00:00:00';
// BETWEEN
db.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.First(&user, "id = ?" , "string_primary_key" ) 
// SELECT * FROM users WHERE id = 'string_primary_key';
// 普通 SQL
 db.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;
// Struct
 db.Find(&users, User{Age: 20 }) 
// SELECT * FROM users WHERE age = 20;
// Map
 db.Find(&users, map [ string ] interface {}{ "age" : 20 }) 
// SELECT * FROM users WHERE age = 20;


Not 条件:

构建 NOT 条件,工作方式类似于Where


db.Not( "name = ?" , "jinzhu" ).First(&user) 
// SELECT * FROM users WHERE NOT name = "jinzhu" ORDER BY id LIMIT 1;
// 不在
db.Not( map [ string ] interface {}{ "name" : [] string { "jinzhu" , "jinzhu 2" }}).Find(&users) 
// SELECT * FROM users WHERE name NOT IN (“金珠”、“金珠2”);
// Struct
 db.Not(User{Name: "jinzhu" , Age: 18 }).First(&user) 
// SELECT * FROM users WHERE name <> "jinzhu" AND age <> 18 ORDER BY id LIMIT 1;
// 不在主键切片中
db.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' ;
// Struct
 db.Where( "name = 'jinzhu'" ).Or(User{Name: "jinzhu 2" , Age: 18 }).Find(&users) 
// SELECT * FROM users WHERE name = 'jinzhu' OR (姓名 = '金珠 2' AND 年龄 = 18);
// Map
 db.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);


限制和偏移


Limit指定要检索的最大记录数Offset指定在开始返回记录之前要跳过的记录数


db.Limit( 3 ).Find(&users) 
// SELECT * FROM users LIMIT 3;
// 使用 -1 取消限制条件
db.Limit( 10 ).Find(&users1).Limit( -1 ).Find(&users2) 
// SELECT * FROM users LIMIT 10; (users1) 
// 选择 * FROM 用户;(用户2)
db.Offset( 3 ).Find(&users) 
// SELECT * FROM users OFFSET 3;
db.Limit( 10 ).Offset( 5 ).Find(&users) 
// SELECT * FROM users OFFSET 5 LIMIT 10;
// 使用 -1 取消偏移条件
db.Offset( 10 ).Find(&users1).Offset( -1 ).Find(&users2) 
// SELECT * FROM users OFFSET 10; (users1) 
// 选择 * FROM 用户;(用户2)


4.更新


简要更新


package main
import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
// 数据表
type UserInfo struct {
  ID    int64
  Name  string
  Hobby string
}
func main() {
  dsn := "root:root@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
  db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
  var userInfo UserInfo
  db.First(&userInfo)
  userInfo.Hobby = "Java"
  userInfo.Name = "dahezhiquan"
  db.Save(&userInfo)
}


更新单个列


当使用 Update 更新单个列时,你需要指定条件,否则会返回 ErrMissingWhereClause 错误


package main
import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)
// 数据表
type UserInfo struct {
  ID    int64
  Name  string
  Hobby string
}
func main() {
  dsn := "root:root@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
  db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
  // var userInfo UserInfo
  db.Model(&UserInfo{}).Where("id = ?", 1).Update("name", "gorm")
}


// 条件更新
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;


5.删除


删除一条记录


删除一条记录时,删除对象需要指定主键,否则会触发 批量 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);
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
7月前
|
SQL 数据库 索引
gorm普通的增删改查
gorm普通的增删改查
68 0
|
7月前
|
安全 程序员 API
GORM概述
GORM概述
62 0
|
7月前
|
JSON 数据库 数据格式
gorm 自定义数据的使用
gorm 自定义数据的使用
68 0
|
7月前
|
SQL 数据库
GORM—查
GORM—查
66 0
|
7月前
|
7月前
|
SQL Go 数据库
gorm 教程 一(1)
gorm 教程 一
81 0
|
7月前
|
数据库
gorm 教程 一(2)
gorm 教程 一
86 0
|
7月前
|
SQL 数据库
gorm 教程 一(3)
gorm 教程 一
108 0
|
7月前
|
SQL 数据库
|
SQL 安全 数据库
GORM V2 写操作
GORM V2 写操作
60 0
下一篇
DataWorks