设计模式之 Database/SQL 与 GORM 实践 | 青训营笔记

419 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第3篇笔记。

本堂课学习了设计模式之 Database/SQL 与 GORM 实践,是字节金柱老师讲授的。这篇文章主要记录自己学习GORM和GEN两部分的内容,及对数据库操作的一些实践。

GORM及实践

安装

适用mod进行依赖管理:go mod init XXX;通过go get 进行依赖安装:

go get  gorm.io/gorm            //gorm依赖
go get  gorm.io/driver/mysql    //mysql依赖

在程序中import导入。 其中GORM在应用程序层面暴露API接口,用户可以通过调用API与数据库交互,数据库进行数据操作,即CRUD操作。

image.png 其中gorm.io/driver/mysql 是数据库驱动的依赖包,实现了GO原生数据库中定义的方法。GO可以通过API与MYSQL进行交互实现CRUD操作。

创建数据库

建表

type User struct {
     UUID    string
     Name    string
     Age     int
     Version int
}

打开数据库

gorm.Open函数打开数据库(DB),输入数据库的密码,并且DB进行命名和相关配置。

image.png

通过AutoMigrate接口实现定义的结构体和数据表对应

image.png

CRUD操作

数据库常说的CRUD,即Create、Read、Update、Delete,下面将通过GORM来简单实现这四个操作。

Create

先创建User的结构体
使用Create函数插入数据

image.png

Read

读数据主要是设定查询条件进行查询,类似Select * FROM TABLE WHERE

创建user变量
设定查询条件,使用First函数进行查找

代码分别查询了第一条数据和name=dance的语句。

image.png

Update

更新也需要先进行查找,然后对某列数据进行重新写入。

查找满足条件的行
Update函数重新写入需要修改的值

image.png

Delete

删除也需要先进行查找。可见数据库的查找是基础

Delete删除

image.png

上述语句打印出来的结果

image.png

最后通过msql的查询语句进行数据查看,查询语句和结果如下:

SELECT * FROM user

image.png

小结

GORM给出了一些接口供用户对数据库操作,便于程序员操作。而其底层仍为数据库的增、查、删、改操作,也是优化的点,如合理设置主键等。

GEN

GEN是由字节跳动无恒实验室与 GORM 作者(https://github.com/jinzhu)联合研发的开源工具。能够通过代码生成方式实现GORM代码封装,可生成对应结构体及CRUD相关代码等,提供用户相关的API。具体可看如何使用。

安装

    go get gorm.io/gen     //gen依赖

在程序中通过import导入

代码生成

package main

import "gorm.io/gen"

// generate code
func main() {
    // specify the output directory (default: "./query")
    // ### if you want to query without context constrain, set mode gen.WithoutContext ###
    g := gen.NewGenerator(gen.Config{
        OutPath: "../dal/query",
        /* Mode: gen.WithoutContext|gen.WithDefaultQuery*/
        //if you want the nullable field generation property to be pointer type, set FieldNullable true
        /* FieldNullable: true,*/
        //if you want to generate index tags from database, set FieldWithIndexTag true
        /* FieldWithIndexTag: true,*/
        //if you want to generate type tags from database, set FieldWithTypeTag true
        /* FieldWithTypeTag: true,*/
        //if you need unit tests for query code, set WithUnitTest true
        /* WithUnitTest: true, */
    })
  
    // reuse the database connection in Project or create a connection here
    // if you want to use GenerateModel/GenerateModelAs, UseDB is necessray or it will panic
    // db, _ := gorm.Open(mysql.Open("root:@(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"))
    g.UseDB(db)
  
    // apply basic crud api on structs or table models which is specified by table name with function
    // GenerateModel/GenerateModelAs. And generator will generate table models' code when calling Excute.
    g.ApplyBasic(model.User{}, g.GenerateModel("company"), g.GenerateModelAs("people", "Person", gen.FieldIgnore("address")))
    
    // apply diy interfaces on structs or table models
    g.ApplyInterface(func(method model.Method) {}, model.User{}, g.GenerateModel("company"))

    // execute the action of code generation
    g.Execute()
}

(图示为官网实例,代码来源:gitee.com/gorm/gen#%E…)

其中可见几个函数

NewGenerator:该函数配置了query和model的输出路径;且默认model的路径和query路径相同
UseDB:该函数的参数为打开的mysql数据库
GenerateModelAs:指定对应表格的结构体名称,参数为定义的结构体和生成的结构体名
ApplyBasic:为指定的结构体或表格生成基础CRUD查询方法
ApplyInterface:插入自定义的查询方法
Execute:执行生成代码

经过执行后形成的代码框架如下:

image.png

图中dal下为自动生成的代码,包括model和query;model为表中存放的数据名称,也就是前面定义的结构体;而query中的代码为数据库操作的相关接口。调用方式为withcontex->具体方法。如:

model.go是自己定义的方法,model中需要自己写SQL语句,函数体内的一些占位符有以下。

gen.T表示指定或structtable
gen.M代表map[string]interface
@@table表示表的名称(如果方法的参数不包含变量,GEN 将从模型结构生成)tabletable
@@<columnName>表示列名或表名
@<name>表示普通查询变量

实践

本次实践是利用GEN随机生成100组数据,并出现相同的UUID时更新其版本。其代码生成如上所述。 实现过程采用了谷歌的UUID包随机生成ID,随后进行ID的随机选取。版本号手动+1。

仓库代码:github.com/zh-lou/byte…

备注: 以上的实践来源于课后作业:juejin.cn/post/709705…

参考链接

GORM学习网站:gorm.cn/zh_CN/docs/…

GEN学习网站:github.com/go-gorm/gen

无恒实验室联合GORM推出安全好用的ORM框架-GEN(推文) mp.weixin.qq.com/s/SfLIkU8E2…