一.Gorm简介
1.什么是Gorm?
Gorm是一个Go语言的数据库框架,它支持对MySQL、PostgreSQL、SQLite和SQL Server等数据库的操作。Gorm提供了一种简洁、灵活且强大的方式来操作数据库,包括创建表、查询数据、更新数据和删除数据等。
2.为什么选择Gorm?
- 全功能 ORM
- 关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承)
- Create,Save,Update,Delete,Find 中钩子方法
- 支持 Preload、Joins 的预加载
- 事务,嵌套事务,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?
安装Gorm需要先安装相应的数据库驱动。例如,要安装MySQL驱动,可以使用命令go get -u gorm.io/gorm和go get -u gorm.io/driver/mysql。安装完成后,可以使用Gorm的Open方法连接数据库,例如db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})。其中,dsn是数据库的连接字符串,包含了数据库的地址、用户名、密码等信息。
需要下载mysql驱动:
go get gorm.io/driver/mysql
go get gorm.io/gorm
简单连接:
username := "root" //账号
password := "root" //密码
host := "127.0.0.1" //数据库地址,可以是Ip或者域名
port := 3306 //数据库端口
Dbname := "gorm" //数据库名
timeout := "10s" //连接超时,10秒
// root:root@tcp(127.0.0.1:3306)/gorm?
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
//连接MYSQL, 获得DB类型实例,用于后面的数据库读写操作。
db, err := gorm.Open(mysql.Open(dsn))
if err != nil {
panic("连接数据库失败, error=" + err.Error())
}
// 连接成功
fmt.Println(db)
高级配置
跳过默认事务: 为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。如果没有这方面的要求,可以在初始化时禁用它,这样可以获得60%的性能提升
db, err := gorm.Open(mysql.Open("gorm.db"), &gorm.Config{
SkipDefaultTransaction: true,
})
命名策略
gorm采用的命名策略是,表名是蛇形复数,字段名是蛇形单数, 例如:
type Student struct {
Name string
Age int
MyStudent string
}
gorm会为我们这样生成表结构:
CREATE TABLE `students` (`name` longtext,`age` bigint,`my_student` longtext)
我们也可以修改这些策略:
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
TablePrefix: "f_", // 表名前缀
SingularTable: false, // 单数表名
NoLowerCase: false, // 关闭小写转换
},
})
二.模型定义
模型是标准的 struct,由 Go 的基本数据类型、实现了 Scanner 和 Valuer 接口的自定义类型及其指针或别名组成
定义一张表:
type Student struct {
ID uint // 默认使用ID作为主键
Name string
Email *string // 使用指针是为了存空值
}
自动生成表结构:
// 可以放多个
DB.AutoMigrate(&Student{})
AutoMigrate的逻辑是只新增,不删除,不修改(大小会修改)
例如将Name修改为Name1,进行迁移,会多出一个name1的字段
生成的表结构如下:
CREATE TABLE `f_students` (`id` bigint unsigned AUTO_INCREMENT,`name` longtext,`email` longtext,PRIMARY KEY (`id`))
修改大小:
我们可以使用gorm的标签进行修改
有两种方式:
Name string `gorm:"type:varchar(12)"`
Name string `gorm:"size:2"`
字段标签:
type 定义字段类型
size 定义字段大小
column 自定义列名
primaryKey 将列定义为主键
unique 将列定义为唯一键
default 定义列的默认值
not null 不可为空
embedded 嵌套字段
embeddedPrefix 嵌套字段前缀
comment 注释
多个标签之前用 ; 连接
type StudentInfo struct {
Email *string `gorm:"size:32"` // 使用指针是为了存空值
Addr string `gorm:"column:y_addr;size:16"`
Gender bool `gorm:"default:true"`
}
type Student struct {
Name string `gorm:"type:varchar(12);not null;comment:用户名"`
UUID string `gorm:"primaryKey;unique;comment:主键"`
Info StudentInfo `gorm:"embedded;embeddedPrefix:s_"`
}
// 建表语句
CREATE TABLE `students` (
`name` varchar(12) NOT NULL COMMENT '用户名',
`uuid` varchar(191) UNIQUE COMMENT '主键',
`s_email` varchar(32),
`s_y_addr` varchar(16),
`s_gender` boolean DEFAULT true,
PRIMARY KEY (`uuid`)
)
三.查询操作
先使用gorm对单张表进行增删改查
表结构
type Student struct {
ID uint `gorm:"size:3"`
Name string `gorm:"size:8"`
Age int `gorm:"size:3"`
Gender bool
Email *string `gorm:"size:32"`
}
添加记录
email := "xxx@qq.com"
// 创建记录
student := Student{
Name: "wcy",
Age: 23,
Gender: True,
Email: &email,
}
DB.Create(&student)
两点需要注意:
- 指针类型是为了更好的存null类型,但是传值的时候,也记得传指针
- Create接收的是一个指针,而不是值
由于我们传递的是一个指针,调用完Create之后,student这个对象上面就有该记录的信息了,如创建的id
DB.Create(&student)
fmt.Printf("%#v\n", student)
// main.Student{ID:0x2, Name:"zhangsan", Age:23, Gender:false, Email:(*string)(0x11d40980)}
批量插入:
Create方法还可以用于插入多条记录
var studentList []Student
for i := 0; i < 100; i++ {
studentList = append(studentList, Student{
Name: fmt.Sprintf("机器人%d号", i+1),
Age: 100,
Gender: True,
Email: &email,
})
}
DB.Create(&studentList)
根据主键查询:
var student Student
DB.Take(&student, 2)
fmt.Println(student)
student = Student{} // 重新赋值
DB.Take(&student, "4")
fmt.Println(student)
Take的第二个参数,默认会根据主键查询,可以是字符串,可以是数字
根据其他条件查询:
var student Student
DB.Take(&student, "name = ?", "机器人27号")
fmt.Println(student)
使用?作为占位符,将查询的内容放入?
SELECT * FROM `students` WHERE name = '机器人27号' LIMIT 1
这样可以有效的防止sql注入
他的原理就是将参数全部转义,如
DB.Take(&student, "name = ?", "机器人27号' or 1=1;#")
SELECT * FROM `students` WHERE name = '机器人27号' or 1=1;#' LIMIT 1
此外,Gorm还提供了一些常用的查询方法,例如Where、Find、First、Select、Order等,可以方便地进行数据的查询和筛选。Gorm还支持链式查询,可以通过链式调用方法来构建复杂的查询条件。
总之,Gorm是一个功能强大、易于使用和灵活的数据库框架,适用于开发各种类型的Go语言应用程序。