写点什么

Go 语言 gorm 框架 MySQL 实践

作者:FunTester
  • 2022 年 1 月 11 日
  • 本文字数:2949 字

    阅读完需:约 10 分钟

gorm 是一个使用 Go 语言编写的 ORM 框架。文档齐全,对开发者友好,支持主流数据库。


我最近在补齐 Go 语言各类基础的框架和操作库的知识,终于进展到了数据库阶段,搜资料的时候基本都是推荐这个框架,可见其之流行程度。在不断尝试练习之后,总结了一些经验和使用方式,供初学者参考。


在之前使用 Java 语言的时候用过两种 JDBC 和 mybatis,一种是本地操作数据库的一种是在 Springboot 项目中使用,两者使用习惯上都是基于 MySQL 语句,都是在操作层面把 MySQL 语句拼写完成。但是在 gorm 框架中几乎看不到完整的 SQL 语句,都是通过方法和参数

go.mod

github.com/jinzhu/gorm v1.9.16


在执行Go Mod Tidy的时候会把相关需要的依赖(这个用词可能不准)自动添加到 mod 文件中。


go.mod我现在也不是很熟悉,我也是抄能力发动+IDE 提示完成的,通常来说比较顺利。


我的代码中依赖如下:


import (  "fmt"  "funtester/base"  "funtester/futil"  "github.com/jinzhu/gorm"  _ "github.com/jinzhu/gorm/dialects/mysql"  "log"  "testing"  "time")
复制代码

初始化

这个演示 Demo,内容偏基础,高阶的我也不会用,目前也用不到。演示分两类:初始化连接,初始化数据库。由于 gorm 自带了数据库初始化功能,会将Model对应数据库表创建(这个需要手动开启),所以这个在测试中还是比较常用的,如果辅以数据初始化的方法,基本满足我们日常开发测试服务的需求。


func init() {  var err error  drive, err = gorm.Open("mysql", "root:root123456@(localhost:3306)/funtester?charset=utf8&parseTime=true")  if err != nil {    fmt.Println(err)    log.Fatalln("mysql conntect err")  }  drive.DB().SetMaxOpenConns(200)  drive.DB().SetConnMaxLifetime(10 * time.Second)  drive.DB().SetConnMaxIdleTime(10 * time.Second)  drive.DB().SetMaxIdleConns(20)  // 迁移 schema  drive.AutoMigrate(&Funtester{})  //注意: AutoMigrate 会创建表,缺少的外键,约束,列和索引,并且会更改现有列的类型(如果其大小、精度、是否为空可更改)。但 不会 删除未使用的列,以保护您的数据。  //db.AutoMigrate(&User{}, &Product{}, &Order{})  //drive.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&Funtester{})//带参数的迁移
}
复制代码

Model

type Funtester struct {  gorm.Model  Name string  Age  int}
复制代码


这里分享一下 MySQL 数据库表结构:


DROP TABLE IF EXISTS `funtesters`;CREATE TABLE `funtesters` (  `id` int unsigned NOT NULL AUTO_INCREMENT,  `name` varchar(255) DEFAULT NULL,  `age` int unsigned DEFAULT NULL,  `created_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  `created_at` datetime DEFAULT NULL,  `updated_at` datetime DEFAULT NULL,  `deleted_at` datetime DEFAULT NULL,  PRIMARY KEY (`id`),  KEY `idx_funtesters_deleted_at` (`deleted_at`)) ENGINE=InnoDB AUTO_INCREMENT=241861 DEFAULT CHARSET=utf8mb3;
SET FOREIGN_KEY_CHECKS = 1;
复制代码


这里应该就比较清晰看到 gorm 初始化数据库的时候的逻辑了。这里分享一下gorm.Model源码:


type Model struct {  ID        uint `gorm:"primary_key"`  CreatedAt time.Time  UpdatedAt time.Time  DeletedAt *time.Time `sql:"index"`}
复制代码

select

下面演示一下 select 常用语法,这里分成了两个:一个偏基础,一个偏复杂(主要是多查询条件串联)。这里可以很明显看出 gorm 拼接查询条件的思路,就是把查询条件分类然后单独写不同的条件,由 gorm 框架做 SQL 语句的拼接。


func TestSelect1(t *testing.T) {  var f Funtester  drive.First(&f, 34)//默认id  last := drive.Last(&f, "age != 1")//添加条件  fmt.Printf("查询到记录数 %d "+base.LINE, last.RowsAffected)  fmt.Println(f)  take := drive.Take(&f) //不指定顺序  fmt.Println(take.RowsAffected)}// TestSelect2// @Description: 常用查询和处理结果// @param tfunc TestSelect2(t *testing.T) {  var fs []Funtester  var f Funtester  drive.Where("id = ?", 45).First(&f)//另外一种写法  //fmt.Println(f)  find := drive.Where("name like ?", "fun%").Find(&fs).Limit(10).Order("id")//多查询条件串联  rows, _ := find.Rows()//获取结果  defer rows.Close()  for rows.Next() {    var ff Funtester    drive.ScanRows(rows, &ff)    fmt.Println(ff.Age, ff.Name)  }  //另外一种写法  var f1 Funtester  drive.Where("name LIKE ?", "fun").Or("id = ?", 123).First(&f1)  fmt.Println(f1)
}
复制代码

update

有了select的基础,再来看update就比较容易了。


// TestUpdate// @Description: 更新// @param tfunc TestUpdate(t *testing.T) {  drive.Model(&Funtester{}).Where("id = ?", 241860).Update("name", base.FunTester+"3")}
复制代码

insert

gorm 官文文档支持批量插入的,但是这个依赖包中并没有相关支持。各位如果使用跟我一样的依赖的话,


// TestInsert// @Description: 增加// @param tfunc TestInsert(t *testing.T) {  value := &Funtester{Name: "FunTester" + futil.RandomStr(10)}  drive.Create(value)  drive.Select("name", "age").Create(value) //只创建name和age字段的值  futil.Sleep(1)  drive.Omit("age", "name").Create(&Funtester{Name: "fds",Age: 122})   //过滤age和name字段创建  fs := []Funtester{{Name: "fs" + futil.RandomStr(10), Age: 12}, {Name: "fs" + futil.RandomStr(10), Age: 12}}  drive.Create(&fs)//这里不支持这么操作的}
复制代码

delete

删除操作跟以上两种操作使用方式一致。


func TestDelete(t *testing.T) {  db := drive.Where("id = ?", 241859).Delete(&Funtester{})  fmt.Println(db.RowsAffected)}
复制代码

执行 SQL

当然 gorm 也是支持直接执行 SQL 语句的,有一个特殊就是执行查询语句的时候需要解析查询结果。


// TestSql// @Description: 直接执行SQL// @param tfunc TestSql(t *testing.T) {  var funtester []Funtester  scan := drive.Raw("select * from funtesters where id > 333 limit 10").Scan(&funtester)  fmt.Println(scan.RowsAffected)  fmt.Println(funtester)}
复制代码

事务 &回滚

在 gorm 高级语法的使用中,我觉得这个是非常实用的,对于一些测试语句的执行非常适合。


// TestRollBack// @Description: 事务&回滚// @param tfunc TestRollBack(t *testing.T) {  funtester := Funtester{Name: base.FunTester, Age: 32232}  begin := drive.Begin()  err := begin.Create(&funtester).Error  if err != nil {    begin.Rollback()  }  begin.Commit()
}
复制代码


gorm 的基本使用已经分享完了,下次分享使用 gorm 做性能测试的实践。

Have Fun ~ Tester !

发布于: 刚刚阅读数: 2
用户头像

FunTester

关注

公众号:FunTester,750篇原创,欢迎关注 2020.10.20 加入

公众号FunTester,坚持原创文章的测试人,一个有趣的灵魂。

评论

发布
暂无评论
Go语言gorm框架MySQL实践