这是我参与「第五届青训营 」伴学笔记创作活动的第5天
Go gorm实践
GORM
GORM是Golang目前比较热门的数据库ORM操作库,对开发者也比较友好,使用非常方便简单,使用上主要就是把struct类型和数据库表记录进行映射,操作数据库的时候不需要直接手写Sql代码,这里主要介绍MySQL数据库。
这里讲解的比较基础,主要就是增删改查 流程:连接数据库->增删改查->事务
链接数据库
连接mysql主要有两个步骤:
- 配置DSN (Data Source Name)
- 使用gorm.Open连接数据库
DSN的格式为:
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
下面为示例:
package consts
var (
// DSN 数据库地址
DSN = "root:123456@tcp(***.**.**.**)/'数据库名称'?charset=utf8mb4&parseTime=True&loc=Local"
)
package global
var (
DB *gorm.DB
)
package main
global.DB, err = gorm.Open(mysql.Open(consts.DSN), &gorm.Config{})
这里我们在consts里定义DSN,在global里定义了gorm.DB,原因呢,是因为个人习惯,一般把常量统一放在consts里,把全局变量放global里
然后在main里我们连接数据库,这里使用gorm.open(),里面的mysql.open是mysql驱动,其它数据库就按其它的写。
增
插入数据我们一般用Create,例子👇
u := User{
Username:"admin",
Password:"123456",
CreateTime:time.Now().Unix(),
}
DB.Create(&u)
这样就插入数据了,这时大家有没有发现一个问题就是,这样的话它插入到哪个表了呢?
这很重要(因为我踩过坑)
比如我们这里是结构体是User,那默认就插入到users表里
那如果为没有users表,想指定其它某个表呢?
诶!那就要用到TableName方法,怎么用,如下:
func(c User)TableName() string {
return "hahaha"
}
在这里就是我们把User的绑定到hahaha表里(如果这个表存在的话),我们的增删改查都会从这个表里进行
删
删除模型数据一般用于删除之前查询出来的模型变量绑定的记录。
用法:db.Delete(),例子如👇
user := User{} //先建立模型
db.Where("id = ?", 2).Take(&user) //查询id为2的一条数据
db.Delete(&user) //删掉
当然,我们还可以这样
db.Where("id = ?", 2).Delete(&User{})//将id==2的删掉
不难哟
改
改的话一般有3种
Saveuser := User{} db.Where("id = ?", 2).Take(&user) // 取出id==2的 user.Name = "song" //改名字 db.Save(&user) //更新Update第二个为什么是把所有name都变呢?因为我们建了一个空结构体,所以where为空db.Model(&user).Update("name", "song")//默认取user的主键作为where的值 db.Model(&User{}).Update("name", "song")//把所有的name都变成song db.Model(&User{}).Where("create_time > ?", "2023-1-22 17:00:00").Update("name", "song")//用where的,这个就不用我多说了吧?UPDATE users SET age = age + 1 WHERE id = '2'这样的带计算表达式的更新语句gorm怎么写? gorm很贴心的提供了表达式db.Model(&user).Update("age",gorm.Expr("age + 1"))
查
gorm是协程安全的,可以并发执行
查询有很多函数我来介绍一下
Take()查询一条记录//等价于:SELECT * FROM users LIMIT 1 db.Take(&user)First()查询一条记录,根据主键ID排序(正序),返回第一条记录//等价于:SELECT * FROM users ORDER BY users.id ASC LIMIT 1 db.First(&user)Last()查询一条记录, 根据主键ID排序(倒序),返回第一条记录Find()查询多条记录,Find函数返回的是一个数组var users []User //等价于:SELECT * FROM users db.Find(&users)Pluck()查询一列值var names []string //等价于:SELECT name FROM users db.Model(&User{}).Pluck("name", &names)
事务
- 自动事务
通过db.Transaction函数实现事务,如果闭包函数返回错误,则回滚事务db.Transaction(func(tx *gorm.DB) error { if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil { // 返回任何错误都会回滚事务 return err } if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil { return err } return nil }) - 手动事务
在开发中经常需要数据库事务来保证多个数据库写操作的原子性
// 开启事务
tx := db.Begin()
rowsAffected := tx.Model(&user).Where("age > 0").Update("age", gorm.Expr("age + 1")).RowsAffected
if rowsAffected == 0 {
tx.Rollback()
return
}
err := tx.Save().Error
//失败,则回滚事务
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
到此结束!!