Contents

Gorm Gen

Contents

Gorm Gen

参考链接:https://www.liwenzhou.com/posts/Go/gen/

Gen是一个基于GORM的安全ORM框架,其主要通过代码生成方式实现GORM代码封装。使用Gen框架能够自动生成Model结构体和类型安全的CRUD代码,极大提升CRUD效率。

const DSN = "postgres://user:password@127.0.0.1:5432/hello?sslmode=disable&TimeZone=Asia/Shanghai&search_path=public"

func connectDB(dsn string) *gorm.DB {
	db, err := gorm.Open(postgres.Open(dsn))
	if err != nil {
		panic(fmt.Errorf("connect db fail: %w", err))
	}
	return db
}


func main() {
	// 指定生成代码的具体相对目录(相对当前文件),默认为:./query
	// 默认生成需要使用WithContext之后才可以查询的代码,但可以通过设置gen.WithoutContext禁用该模式
	g := gen.NewGenerator(gen.Config{
		// 默认会在 OutPath 目录生成CRUD代码,并且同目录下生成 model 包
		// 所以OutPath最终package不能设置为model,在有数据库表同步的情况下会产生冲突
		// 若一定要使用可以通过ModelPkgPath单独指定model package的名称
		OutPath:      "data/query",
		ModelPkgPath: "data/model",
		// 生成 gorm 标签的字段类型属性
		FieldWithTypeTag: true,
		// 表字段可为 null 值时, 对应结体字段使用指针类型
		FieldNullable: true,
		// gen.WithoutContext:禁用WithContext模式
		// gen.WithDefaultQuery:生成一个全局Query对象Q
		// gen.WithQueryInterface:生成Query接口
		Mode: gen.WithDefaultQuery,
	})

	// 通常复用项目中已有的SQL连接配置db(*gorm.DB)
	// 非必需,但如果需要复用连接时的gorm.Config或需要连接数据库同步表信息则必须设置
	g.UseDB(connectDB(DSN))

	// 从连接的数据库为所有表生成Model结构体和CRUD代码
	// 也可以手动指定需要生成代码的数据表

	dataTypeMap := map[string]func(gorm.ColumnType) (dataType string){
		"numeric": func(columnType gorm.ColumnType) string { return "decimal.Decimal" },
		"int4":    func(columnType gorm.ColumnType) string { return "int64" },
		"int2":    func(columnType gorm.ColumnType) string { return "int64" },
		"serial4": func(columnType gorm.ColumnType) string { return "int64" },
	}
	g.WithDataTypeMap(dataTypeMap)
	g.ApplyBasic(g.GenerateAllTable()...)

	// 执行并生成代码
	g.Execute()

表关联


// foreignKey:  action 表中的字段,action表中的id
// references: user表中的字段,user表中的 action_id
    action := g.GenerateModel("action")
	user := g.GenerateModel("user",
		gen.FieldRelate(field.HasMany, "actions", action,
			&field.RelateConfig{
				RelateSlicePointer: true,
				GORMTag: field.GormTag{
					"foreignKey": []string{
						"ID",
					},
					"references": []string{
						"ActionID",
					},
				},
			},
		),
	)

基于索引的情况下批量更新或者新增

	err = pa.WithContext(ctx).Clauses(
		clause.OnConflict{
			Columns: []clause.Column{
				{Name: user.Code.ColumnName().String()},
			},
			TargetWhere: clause.Where{
				Exprs: []clause.Expression{
					clause.Expr{
						SQL: "deleted_at = 0",
					},
				},
			},
			DoUpdates: clause.AssignmentColumns(cols),
		},
	).
		CreateInBatches(items, 30)