前言 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 mainimport ( "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():重新映射表名column:重新指定MySQL数据表的字段的映射关系
1 2 3 4 5 6 7 8 type User struct { gorm.Model Key string `gorm:"column:key"` } func (User) TableName() string { return "user" }
新增
1 err := db.Create(&User{ID: 1 , Key: "value" }).Error
删除 根据主键删除
1 err := db.Delete(&User{ID: 1 }).Error
根据条件删除 1 err := db.Where("id = ?" , 1 ).Delete(&User{}).Error
修改 根据主键覆盖所有字段
自动根据主键覆盖所有字段,零值字段也会 被覆盖
如果数据存在,则覆盖;如果数据不存在,则新增
1 db.Save(&User{ID: 1 , Key: "value" })
根据主键更新所有字段
通过结构体更新 1 err := db.Model(&User{}).Updates(&User{ID: 1 , Key: "value" }).Error
通过映射更新 1 2 3 4 err := db.Model(&User{}).Updates(map [string ]string { "id" : 1 , "key" : "value" , }).Error
根据条件更新指定字段
根据条件更新指定字段,零值字段也会 被更新
通过Model()指定结构体,间接指定数据表名
1 err := db.Model(&User{}).Where("id = 1" ).Update("key" , "value" ).Error
1 err := db.Table("user" ).Where("id = 1" ).Update("key" , "value" ).Error
通过SQL表达式更新 1 err := db.Model(&User{}).Where("id = 1" ).Update("id" , gorm.Expr("id + ?" , 1 )).Error
查询 查询所有数据 1 2 3 var userList []User{}err := db.Find(&userList).Error
查询单个数据
1 2 3 var user User{}err := db.First(&user).Error
Where子句
比较运算符
=:等于!=、<>:不等于<:小于<=:小于等于>:大于>=:大于等于
1 2 3 var userList []User{}err := db.Where("id = ?" , 1 ).Find(&userList).Error
1 2 3 var userList []User{}err := db.Where("created_at > ?" , time.Now()).Find(&userList).Error
IN 1 2 3 var userList []User{}err := db.Where("id IN (?)" , []int {1 , 2 }).Find(&userList).Error
LIKE 1 2 3 var userList []User{}err := db.Where("id LIKE ?" , "%1%" ).Find(&userList).Error
AND 1 2 3 var userList []User{}err := db.Where("id >= ? AND id <= ?" , 0 , 2 ).Find(&userList).Error
1 2 3 var userList []User{}err := db.Where("id >= ?" , 0 ).And("id <= ?" , 2 ).Find(&userList).Error
OR 1 2 3 var userList []User{}err := db.Where("id <= ? OR id >= ?" , 0 , 2 ).Find(&userList).Error
1 2 3 var userList []User{}err := db.Where("id <= ?" , 0 ).Or("id >= ?" , 2 ).Find(&userList).Error
BETWEEN…AND 1 2 3 var userList []User{}err := db.Where("id BETWEEN ? AND ?" , 0 , 2 ).Find(&userList).Error
1 2 3 var userList []User{}err := db.Where("id NOT BETWEEN ? AND ?" , 0 , 2 ).Find(&userList).Error
NULL 1 2 3 var userList []User{}err := db.Where("id IS NULL" ).Find(&userList).Error
1 2 3 var userList []User{}err := db.Where("id IS NOT NULL" ).Find(&userList).Error
Select子句 1 2 3 var userList []User{}err := db.Select("id, key" ).Find(&userList).Error
使用聚合函数 1 2 3 var result int64 err := db.Select("MAX(id)" ).Scan(&result).Error
OrderBy子句 排序单次 1 2 3 var userList []User{}err := db.Order("id asc" ).Find(&userList).Error
排序多次 1 2 3 var userList []User{}err := db.Order("id asc" ).Order("username desc" ).Find(&userList).Error
自定义规则排序 1 2 3 var userList []User{}err := db.Order("FIELD(key, '排在前面的值', '排在后面的值')" ).Find(&userList).Error
以切片变量作为参数传递自定义规则 1 2 3 var userList []User{}err := db.Clauses(clause.OrderBy{Expression: clause.Expr{SQL: "FIELD(key, ?)" , Vars: []interface {}{[]string {"排在前面的值" , "排在后面的值" }}, WithoutParentheses: true }}).Find(&userList).Error
Limit子句和Offset子句 分页查询
pageSize:每页的数据量pageNum:当前页的页码
1 2 3 4 5 var userList []User{}var pageSize = 1 var pageNumber = 1 err := db.Limit(pageSize).Offset((pageNumber-1 )*pageSize).Find(&userList).Error
查询总数 1 2 3 var count int64 err := db.Model(&User{}).Where("id = ?" , 1 ).Count(&count).Error
查询某一列的所有数据 1 2 3 var userKeyList []string {}err := db.Distinct("key" ).Pluck("key" , &userKeyList).Error
执行原生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:当前表的外键references:另一个表的主键
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;references: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)
根据地址id为1的数据查询用户
1 2 3 userList := []User{} db.Preload("Address" , "id = ?" , 1 ).Find(&userList)
HasOne
foreignKey:另一个表的外键references:当前表的主键
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;references:ID"` } func (Address) TableName() string { return "address" }
1 2 3 addressList := []Address{} db.Preload("User" ).Find(&addressList)
多对一
HasMany
foreignKey:另一个表的外键references:当前表的主键
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;references:ID"` } func (Address) TableName() string { return "address" }
1 2 3 addressList := []Address{} db.Preload("User" ).Find(&addressList)
多对多
ManyToMany
foreignKey:当前表主键joinForeignKey:关联表与当前表关联的外键References:另一个表的主键joinReferences:关联表与另一个表关联的外键
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;foreignKey:ID;joinForeignKey:UserID;References:UUID;joinReferences:AddressUUID"` } func (User) TableName() string { return "user" } type Address struct { UUID string Address string } func (Address) TableName() string { return "address" } type UserAddress struct { ID int UserID int AddressUUID 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 mainimport ( "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官方文档 腾讯开发者社区——堕落飞鸟 博客园——TY520