Go gorm实践 | 青训营笔记

123 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第5天

Go gorm实践

GORM

GORM是Golang目前比较热门的数据库ORM操作库,对开发者也比较友好,使用非常方便简单,使用上主要就是把struct类型和数据库表记录进行映射,操作数据库的时候不需要直接手写Sql代码,这里主要介绍MySQL数据库。

这里讲解的比较基础,主要就是增删改查 流程:连接数据库->增删改查->事务

链接数据库

连接mysql主要有两个步骤:

  1. 配置DSN (Data Source Name)
  2. 使用gorm.Open连接数据库

DSN的格式为:
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=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种

  1. Save
    user := User{} 
    db.Where("id = ?", 2).Take(&user) // 取出id==2的
    user.Name = "song" //改名字
    db.Save(&user) //更新
    
  2. Update
    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的,这个就不用我多说了吧?
    
    第二个为什么是把所有name都变呢?因为我们建了一个空结构体,所以where为空
  3. UPDATE users SET age = age + 1 WHERE id = '2' 这样的带计算表达式的更新语句gorm怎么写? gorm很贴心的提供了表达式
    db.Model(&user).Update("age",gorm.Expr("age + 1"))
    

gorm是协程安全的,可以并发执行

查询有很多函数我来介绍一下

  1. Take() 查询一条记录
    //等价于:SELECT * FROM users LIMIT 1 
    db.Take(&user)
    
  2. First() 查询一条记录,根据主键ID排序(正序),返回第一条记录
    //等价于:SELECT * FROM users ORDER BY users.id ASC LIMIT 1 
    db.First(&user)
    
  3. Last() 查询一条记录, 根据主键ID排序(倒序),返回第一条记录
  4. Find() 查询多条记录,Find函数返回的是一个数组
    var users []User 
    //等价于:SELECT * FROM users 
    db.Find(&users)
    
  5. 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() 
  }

到此结束!!