Gorm基本使用 | 青训营笔记

93 阅读3分钟

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

Gorm基本使用

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

初始化

初始化连接,初始化数据库。由于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 t
func 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 t
func TestUpdate(t *testing.T) {
 drive.Model(&Funtester{}).Where("id = ?", 241860).Update("name", base.FunTester+"3")
}

insert

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

// TestInsert
// @Description: 增加
// @param t
func 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 t
func 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 t
func 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的基本使用已经分享完了.