Gorm与Gorm Gen实践|青训营

255 阅读4分钟

Gorm与Gorm Gen实践

众所周知,DAO层是后端服务的重要组成部分,在学习Go 语言工程实践之测试课程时,老师给予了完整的源代码。看到老师们设计的DAO层,甚是羡慕。但是对于我这样刚接触GO语言的人来说,直接上手完成DAO层有些困难,于是便学习了Gorm Gen已实现自动化生成DAO层。

Gorm Gen简介

Gorm官方提供了一个可以自动生成数据库结构体的工具:Gen

这个工具不仅仅可以用来生成数据表对应的模型文件,还提供了更加安全以及方便的API。

1.Gorm Gen安装

目前Gorm Gen在Gorm.io下,直接引入即可。不需要额外的安装。

2.配置数据库

Gorm Gen依赖配置好的数据库生成DAO层,官方文档中的数据库为SQLite,在这里我使用了MySql作为演示。数据库使用了Go 语言工程实践之测试课程中老师使用的数据库。

数据库模型如下图所示。

image-20230731233658382.png

3.编写自动生成代码

package main

import (
	"gorm.io/driver/mysql"
	"gorm.io/gen"
	"gorm.io/gorm"
)

func main() {
	// Initialize the generator with configuration
	g := gen.NewGenerator(gen.Config{
		OutPath:           "./dal", // output directory, default value is ./query
		ModelPkgPath:      "./mode",
		Mode:              gen.WithDefaultQuery | gen.WithQueryInterface | gen.WithoutContext,
		FieldNullable:     true,
		FieldCoverable:    false,
		FieldSignable:     false,
		FieldWithIndexTag: false, // generate with gorm index tag
		FieldWithTypeTag:  true,  // generate with gorm column type tag
	})
	dsn := "root:1xxxxxxxx1@tcp(localhost:3306)/community?charset=utf8mb4&parseTime=True&loc=Local"
	// Initialize a *gorm.DB instance
	db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	g.UseDB(db)
	User := g.GenerateModel("user")
	Post := g.GenerateModel("post")
	Topic := g.GenerateModel("topic")
	g.ApplyBasic(User, Post, Topic)
	// Use the above `*gorm.DB` instance to initialize the generator,
	// which is required to generate structs from db when using `GenerateModel/GenerateModelAs`

	// Execute the generator
	g.Execute()
}

main函数中,创建了一个Gorm-gen的代码生成器g,并使用了gen.Config结构来配置生成器的行为。配置项包括:

  • OutPath:生成的代码输出目录,这里设置为./dal,即当前目录下的dal文件夹。
  • ModelPkgPath:指定模型的包路径,这里设置为./mode,即当前目录下的mode文件夹。
  • Mode:生成器的模式,这里使用了gen.WithDefaultQuery | gen.WithQueryInterface | gen.WithoutContext,表示生成默认查询方法、查询接口方法,并且不使用Context(即不生成WithContext方法)。
  • FieldNullable:是否生成字段的可空标志,默认为true,表示字段会生成为指针类型。
  • FieldCoverable:是否生成字段的Cover方法,默认为false,Cover方法用于覆盖模型字段值。
  • FieldSignable:是否生成字段的Sign方法,默认为false,Sign方法用于对字段值进行签名。
  • FieldWithIndexTag:是否生成Gorm的index标签,默认为false,表示不生成index标签。
  • FieldWithTypeTag:是否生成Gorm的column类型标签,默认为true,表示生成column类型标签。

接下来,定义了数据库连接字符串dsn,用于连接到MySQL数据库。然后,通过gorm.Open方法创建了一个Gorm数据库实例db,并将其传递给生成器gUseDB方法。这样,生成器就知道要连接到哪个数据库,并可以使用该数据库的信息来生成模型代码。

然后,通过g.GenerateModel方法分别生成了三个模型:User、Post和Topic。这些模型对应着数据库中的三个表,并且包含了对应表的字段信息、查询方法等。

接着,通过g.ApplyBasic方法为生成的三个模型应用基本的增删改查功能,这样生成的模型将具有基本的CRUD(Create, Read, Update, Delete)操作。

最后,通过g.Execute方法来执行代码生成器,它会根据之前的配置和定义生成模型代码,并输出到指定的输出目录。

**对于gen.Config参数的解释,是我个人的理解,如有错误请批评指正。**由于我对Gorm的学习不足,因此无法确定gen.Config的参数在实际运行中会对数据库与Go程序产生何种影响。

4.测试生成的代码

func main() {
    dsn := "root:1xxxxxxxx1@tcp(localhost:3306)/community?charset=utf8mb4&parseTime=True&loc=Local"
    db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    dal.SetDefault(db)
    u := &mode.User{
       ID:         3,
       Name:       "张XX",
       Level:      2,
       CreateTime: time.Now(),
       ModifyTime: time.Now(),
    }
    err := dal.User.Create(u)
    if err != nil {
       fmt.Println(err)
    }
}

测试结果

image-20230731234619606.png

总结

首先,GORM gen官方文档中的实例在Goland中无法运行,有报错。

第二点,ModelPkgPath生成的是struct,而OutPath中生成的是数据操作接口,但是如果忽略ModelPkgPath则不会生成struct,这导致dal中的函数出现错误,但是生成过程中没有提示,这一点很奇怪。目前官网与其他教程中均未使用这个参数。