前言
Go语言通过Gorm操作Mysql数据库
下载依赖
1 2
| go get gorm.io/gorm go get gorm.io/driver/mysql
|
获取数据库连接
<username>
:用户名
<password>
:密码
<ip>
:IP
<port>
:端口号
<databasename>
:数据库名
charset=utf8mb4
:指定字符集
&gorm.Config{}
:指定配置
QueryFields: true
:输出执行的SQL日志
SkipDefaultTransaction: true
:禁用事务
1 2 3 4 5 6 7 8 9 10 11
| package main
import ( "gorm.io/driver/mysql" "gorm.io/gorm" )
func main() { dsn := "<username>:<password>@tcp(<ip>:<port>)/<databasename>?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) }
|
创建实体
- 继承
gorm.Model
结构体
- 结构体名
- 如果结构体名是User,那么映射的数据表名默认为users
- 如果结构体名是UserTable,那么映射的数据表名默认为user_table
- 字段名
- 如果字段名是ID,那么映射的数据表字段名默认为id
- 如果字段名是UserID,那么映射的数据表名默认为user_id
TableName()
:重新映射表名
1 2 3 4 5 6 7 8
| type User struct { gorm.Model Username string }
func (User) TableName() string { return "user" }
|
新增
1 2 3
| user := User{ID: 1, Username: ""}
db.Create(&user)
|
删除
1 2 3
| user := User{ID: 1}
db.Delete(&user)
|
添加条件
1 2 3
| user := User{}
db.Where("id > 1").Delete(&user)
|
修改
覆盖
- 覆盖所有字段,无论是否为零值
- 如果数据存在,则覆盖;如果数据不存在,则新增
1 2 3
| user := User{ID: 1, Username: ""}
db.Save(&user)
|
更新
修改单个字段
1 2 3
| user := User{}
db.Model(&user).Where("id = 1").Update("Username", "")
|
1 2 3
| user := User{}
db.Table("user").Where("id = 1").Update("Username", "")
|
更新所有字段
通过结构体更新
1 2 3
| user := User{Username: ""}
db.Model(&user).Updates(&user)
|
1 2 3
| user := User{Username: ""}
db.Table("user").Updates(&user)
|
通过映射更新
1 2 3
| user := map[string]string{"Username": ""}
db.Table("user").Updates(&user)
|
查询
Where子句
查询全部数据
1 2 3
| userList := []User{}
db.Find(&userList)
|
查询单条数据
1 2 3
| user := User{ID: 1}
db.Find(&user)
|
查询结果集的第一条数据
1 2 3
| userList := []User{}
db.First(&userList)
|
根据条件查询数据
占位符
1 2 3
| userList := []User{}
db.Where("id > ?", 1).Find(&userList)
|
算数运算
相等运算
1 2 3
| user := User{}
db.Where("id = ?", 1).Find(&user)
|
1 2 3
| userList := []User{}
db.Where("id <> ?", 1).Find(&userList)
|
其他算数运算
>
:大于
<
:小于
>=
:大于等于
<=
:小于等于
!=
:不等于
1 2 3
| userList := []User{}
db.Where("id > ?", 1).Find(&userList)
|
包含判断
1 2 3
| userList := []User{}
db.Where("id IN (?)", []int{0, 2}).Find(&userList)
|
模糊查询
1 2 3
| userList := []User{}
db.Where("id LIKE ?", "%1%").Find(&userList)
|
逻辑运算
且
1 2 3
| userList := []User{}
db.Where("id > ? AND id < ?", 0, 2).Find(&userList)
|
或
1 2 3
| userList := []User{}
db.Where("id = ? OR id = ?", 0, 2).Find(&userList)
|
1 2 3
| userList := []User{}
db.Where("id = ?", 0).Or("id = ?", 2).Find(&userList)
|
时间判断
1 2 3
| userList := []User{}
db.Where("time > ?", time).Find(&userList)
|
区间判断
在…之间
1 2 3
| userList := []User{}
db.Where("id BETWEEN ? AND ?", 0, 2).Find(&userList)
|
不在…之间
1 2 3
| userList := []User{}
db.Where("id NOT BETWEEN ? AND ?", 0, 2).Find(&userList)
|
空判断
空
1 2 3
| userList := []User{}
db.Where("id IS NULL").Find(&userList)
|
非空
1 2 3
| userList := []User{}
db.Where("id IS NOT NULL").Find(&userList)
|
Select子句
1 2 3
| userList := []User{}
db.Select("id, username").Find(&userList)
|
OrderBy子句
排序单次
1 2 3
| userList := []User{}
db.Order("id asc").Find(&userList)
|
排序多次
1 2 3
| userList := []User{}
db.Order("id asc").Order("username desc").Find(&userList)
|
Limit子句
Offset()
:跳过几条数据
Limit()
:每页的数据总数
1 2 3
| userList := []User{}
db.Offset(1).Limit(2).Find(&userList)
|
计算数据总数
1 2 3 4
| userList := []User{} var count int64
db.Find(&userList).Count(&count)
|
使用原生SQL语句
<sql>
:SQL语句
执行没有返回值的SQL语句
1
| db.Exec("DELETE FROM user WHERE id = ?", 1)
|
执行有返回值的SQL语句
1 2 3
| userList := []User{}
db.Raw("SELECT * FROM user").Scan(&userList)
|
多表关联
一对一
BelongsTo
- 默认主键在结构体中的属性名是
ID
,在数据库中的属性名是id
- 默认外键(逻辑外键)在结构体中的属性名是
XxxID
,在数据库中的属性名是xxx_id
,关联xxx
数据表的id
字段
foreignKey:属性名
:指定外键
reference:ID
:指定主键
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| type User struct { ID int Username string AddressID string Address Address `gorm:"foreignKey:AddressID;reference:ID"` }
func (User) TableName() string { return "user" }
type Address struct { ID int Address string }
func (Address) TableName() string { return "address" }
|
Address
:此处是关联表属性的属性名,用于存放关联表数据
1 2 3
| userList := []User{}
db.Preload("Address").Find(&userList)
|
HasOne
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| type User struct { ID int Username string AddressID string }
func (User) TableName() string { return "user" }
type Address struct { ID int Address string User User `gorm:"foreignKey:AddressID;reference:ID"` }
func (Address) TableName() string { return "address" }
|
1 2 3
| addressList := []Address{}
db.Preload("User").Find(&addressList)
|
多对一
HasMany
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| type User struct { ID int Username string AddressID string }
func (User) TableName() string { return "user" }
type Address struct { ID int Address string User []User `gorm:"foreignKey:AddressID;reference:ID"` }
func (Address) TableName() string { return "address" }
|
1 2 3
| addressList := []Address{}
db.Preload("User").Find(&addressList)
|
多对多
ManyToMany
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| type User struct { ID int Username string Address []Address `gorm:"many2many:user_address"` }
func (User) TableName() string { return "user" }
type Address struct { ID int Address string }
func (Address) TableName() string { return "address" }
type UserAddress struct { ID int UserID string AddressID string }
func (UserAddress) TableName() string { return "user_address" }
|
1 2 3
| userList := []User{}
db.Preload("Address").Find(&userList)
|
排除条件
1 2 3
| userList := []User{}
db.Preload("Address", "id != ?", 1).Find(&userList)
|
将结果重新排序
1 2 3
| db.Preload("Address", func(db *gorm.DB) *gorm.DB { return db.Order("id asc") }).Find(&user)
|
事务
禁用事务
- gorm的事务默认是开启的,如果不需要使用事务需要禁用事务
1 2 3 4 5 6 7 8 9 10 11 12 13
| package main
import ( "gorm.io/driver/mysql" "gorm.io/gorm" )
func main() { dsn := "<username>:<password>@tcp(<ip>:<port>)/<databasename>?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ SkipDefaultTransaction: true, }) }
|
使用事务
开启事务
通过事务执行SQL
提交事务
回滚事务
异常情况回滚事务
1 2 3 4 5
| defer func() { if r := recover(); r != nil { tx.Rollback() } }
|
完成
参考文献
哔哩哔哩——筱筱知晓
Gorm官方文档