为hade增加model自动生成功能

大家好,我是轩脉刃。

我们写业务的时候和db接触是少不了的,那么要生成model也是少不了的,如何自动生成model,想着要给hade框架增加个这样的命令。

看了下网上的几个开源项目,最终聚焦在两个项目中:

https://github.com/go-gorm/gen

https://github.com/xxjwxc/gormt

gormt的gui是非常强大的,看文档都支持终端gui和windows的gui。但是gormt是一个工具,无法在另外一个项目中引入。

但是gen项目是gorm官方推出的,有jinzhu作者的参与。

所以我尝试选择gen项目来。

gen

gen其实不只是工具,它更像一个全新的orm封装。gen项目生成出来的文件有其实有两个部分,一个是model,就是db的表和对应的model,以xxx.gen.go 命名。而另一个部分是每个model对应一套gen函数,这套gen函数基本上是对orm的二次封装了。

为hade增加model自动生成功能

当然这套函数是基于gorm来封装的,不过你可以完全脱离gorm来使用这套函数。

生成的方法示例如下:

g := gen.NewGenerator(gen.Config{
            OutPath:      "/Users/yejianfeng/Documents/workspace/gohade/hade/app/dal",
            ModelPkgPath: "/Users/yejianfeng/Documents/workspace/gohade/hade/app/dal/model",
            WithUnitTest: true,

            FieldNullable:     false,
            FieldCoverable:    true,
            FieldWithIndexTag: false,
            FieldWithTypeTag:  false,

            Mode: gen.WithDefaultQuery,
        })
        gormService := container.MustMake(contract.ORMKey).(contract.ORMService)
        db, err := gormService.GetDB(orm.WithConfigPath("database.default"))
        if err != nil {
            return err
        }

        g.UseDB(db)
        g.WithDataTypeMap(dataMap)
        //g.WithJSONTagNameStrategy(func(c string) string { return "-" })

        //g.ApplyBasic(model.Customer{})
        //g.ApplyBasic(g.GenerateAllTable()...)
        //g.GenerateModel("users")
        //g.GenerateModel("answers")
        //g.GenerateAllTable()
        g.ApplyBasic(g.GenerateAllTable()...)
        g.Execute()

使用起来像是这样:

u := query.Use(db).User

// Get first matched record
user, err := u.WithContext(ctx).Where(u.Name.Eq("modi")).First()
// SELECT * FROM users WHERE name = 'modi' ORDER BY id LIMIT 1;

// Get all matched records
users, err := u.WithContext(ctx).Where(u.Name.Neq("modi")).Find()
// SELECT * FROM users WHERE name <> 'modi';

// IN
users, err := u.WithContext(ctx).Where(u.Name.In("modi", "zhangqiang")).Find()
// SELECT * FROM users WHERE name IN ('modi','zhangqiang');

// LIKE
users, err := u.WithContext(ctx).Where(u.Name.Like("%modi%")).Find()
// SELECT * FROM users WHERE name LIKE '%modi%';

最终生成的文件如下:

为hade增加model自动生成功能

gen有一些高级的功能:

  • 自定义模型函数,且提供了通过sql语句的注释自实现函数的方法
  • 提供了单元测试框架,你可以自己定义TestCase,来实现对某个自实现函数的单测
  • 智能字段查询,在select语句的时候,可以根据输出对象自动生成select的field

其实gen更像是另一个orm框架了,和facebook的ent类似,为每个model生成一套orm方法。gen是字节跳动的无恒实验室开发的产品,据说字节内部正在将gorm切换到gen。gen的主打是安全,意思是,如果你的orm是完全使用gen来生成的,通过注释sql而不是自己裸写sql来生成,它更能保证安全性。(当然,因为所有的实现代码都是gen来自动生成的)。

我目前的认知还是觉得这套东西太重了一些,整个熟悉下来无异于需要了解另外一个orm框架的语法了。在使用gorm和gen上并没有什么太大的区别。

// &#x63D2;&#x5165;&#x4E00;&#x6761;&#x6570;&#x636E;
    email := "foo@gmail.com"
    name := "foo"
    user := &model.User{
        ID:        0,
        Username:  name,
        Password:  "",
        Email:     email,
        CreatedAt: time.Time{},
    }
    dal.SetDefault(db)
    err := dal.User.WithContext(c).Create(user)
    if err != nil {
        c.AbortWithError(50001, err)
        return
    }
// &#x63D2;&#x5165;&#x4E00;&#x6761;&#x6570;&#x636E;
    email := "foo@gmail.com"
    name := "foo"
    age := uint8(25)
    birthday := time.Date(2001, 1, 1, 1, 1, 1, 1, time.Local)
    user := &User{
        Name:         name,
        Email:        &email,
        Age:          age,
        Birthday:     &birthday,
        MemberNumber: sql.NullString{},
        ActivatedAt:  sql.NullTime{},
        CreatedAt:    time.Now(),
        UpdatedAt:    time.Now(),
    }
    err = db.Create(user).Error
    logger.Info(c, "insert user", map[string]interface{}{
        "id":  user.ID,
        "err": err,
    })

而且如果要写出官网给出的这么复杂的语句:

p := query.Use(db).Pizza

pizzas, err := p.WithContext(ctx).Where(
    p.WithContext(ctx).Where(p.Pizza.Eq("pepperoni")).

        Where(p.WithContext(ctx).Where(p.Size.Eq("small")).Or(p.Size.Eq("medium"))),
).Or(
    p.WithContext(ctx).Where(p.Pizza.Eq("hawaiian")).Where(p.Size.Eq("xlarge")),
).Find()

// SELECT * FROM pizzas WHERE (pizza = "pepperoni" AND (size = "small" OR size = "medium")) OR (pizza = "hawaiian" AND size = "xlarge")

我相信对新手来说真是一个不大容易的事情。

所以目前我还只倾向于使用gen的生成model的部分。

自动生成model命令设计

首先设计一下这个命令的产品形态。

./hade model gen --output=document/app/model/ --database=database.default

在命令行中的参数:

output: &#x5FC5;&#x9009;&#xFF0C;&#x8868;&#x793A;&#x8F93;&#x51FA;&#x7684;&#x8DEF;&#x5F84;
database: &#x53EF;&#x9009;&#xFF0C;&#x9ED8;&#x8BA4;&#x4F7F;&#x7528;database.default

如果没有设置db,或者output没有设置,直接返回错误。

第一步是一个交互命令行工具,首先展示要生成的表列表选择:

&#x8BF7;&#x9009;&#x62E9;&#x8981;&#x751F;&#x6210;&#x6A21;&#x578B;&#x7684;&#x8868;&#x683C;&#xFF1A;
[] *
[] users
[] answers
[] questions

第二步确认要生成的目录和文件,以及覆盖提示:

&#x7EE7;&#x7EED;&#x4E0B;&#x5217;&#x64CD;&#x4F5C;&#x4F1A;&#x5728;&#x76EE;&#x5F55;&#xFF08;xxxx&#xFF09;&#x751F;&#x6210;&#x4E0B;&#x5217;&#x6587;&#x4EF6;&#xFF1A;
user.gen.go(&#x8986;&#x76D6;)
answer.gen.go(&#x65B0;&#x6587;&#x4EF6;)

&#x8BF7;&#x786E;&#x8BA4;&#x662F;&#x5426;&#x7EE7;&#x7EED;&#xFF1F;&#xFF08;Y/N&#xFF09;

第三步选择后是一个生成模型的选项:

&#x8BF7;&#x9009;&#x62E9;&#x6A21;&#x578B;&#x89C4;&#x5219;&#xFF1A;
[] FieldNullable, &#x5BF9;&#x4E8E;&#x6570;&#x636E;&#x5E93;&#x7684;&#x53EF;null&#x5B57;&#x6BB5;&#x8BBE;&#x7F6E;&#x6307;&#x9488;
[] FieldCoverable, &#x6839;&#x636E;&#x6570;&#x636E;&#x5E93;&#x7684;Default&#x8BBE;&#x7F6E;&#x5B57;&#x6BB5;&#x7684;&#x9ED8;&#x8BA4;&#x503C;
[] FieldWithIndexTag, &#x6839;&#x636E;&#x6570;&#x636E;&#x5E93;&#x7684;&#x7D22;&#x5F15;&#x5173;&#x7CFB;&#x8BBE;&#x7F6E;&#x7D22;&#x5F15;&#x6807;&#x7B7E;
[] FieldWithTypeTag, &#x751F;&#x6210;&#x7C7B;&#x578B;&#x5B57;&#x6BB5;

最后一步就是生成模型文件了。

自动生成model命令实现

了解了gen和命令的设计,实现就很简单了。

大概就分几步吧:

  • 获取数据库中的所有表
  • 让用户多选要生成model的表格
  • 和现有的目录中的文件进行比对
  • 让用户多选要生成的model的选项,比如是否可null,是否有default设置等
  • 使用gen生成模型文件

具体代码在 https://github.com/gohade/hade/blob/feature/model-gen/framework/command/model/model.go

其中代码实现方便稍微有几个地方要注意下:

如何查询一个数据库中的所有表

使用gorm很方便就实现了

dbTables, err := db.Migrator().GetTables()

当用户选择了要生成的表格,要和硬盘中已有的文件进行比对,如何操作

这里其实涉及到两个集合的交集和差集

我发现collection库之前已经实现了差集,但是没有实现交集。

这里我补充实现了colleciton的交集,Intersect,并且将collection库升级到1.4.1

// Intersect &#x6BD4;&#x8F83;&#x4E24;&#x4E2A;&#x6570;&#x7EC4;&#xFF0C;&#x83B7;&#x53D6;&#x4E24;&#x4E2A;&#x6570;&#x7EC4;&#x4EA4;&#x96C6;&#xFF0C;&#x4EC5;&#x5BF9;&#x57FA;&#x7840;&#x5143;&#x7D20;&#x751F;&#x6548;
Intersect (arr ICollection) ICollection

gen 库如何只生成model不生成gen文件?

g.UseDB(db)

for _, table := range genTables {
    g.GenerateModel(table)
}
g.Execute()

model命令验证

验证一下要model/gen命令

第一步,使用 ./hade model gen --output=app/model

为hade增加model自动生成功能

选择其中的两个表,answers和questions,提示目录文件

为hade增加model自动生成功能

下一步确认y继续

为hade增加model自动生成功能

最后生成模型成功

为hade增加model自动生成功能

查看文件,确实生成了model

为hade增加model自动生成功能

功能完结。

Original: https://www.cnblogs.com/yjf512/p/15895168.html
Author: 轩脉刃
Title: 为hade增加model自动生成功能

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/554366/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • CAIL2021-阅读理解任务-数据预处理模块(二)

    代码地址:https://github.com/china-ai-law-challenge/CAIL2021/ /* * @Author: Yue.Fan * @Date: 20…

    技术杂谈 2023年6月1日
    097
  • 实战!使用pano2vr生成html5全景页面【转】

    随着现代视觉技术的进步以及对空间展示的迫切需求,很多的无人机可以拍出360度甚至720度全景照片,怎样将全景地图以html5的形式展示出来?文章将详细讲解如何使用pano2vr.e…

    技术杂谈 2023年5月31日
    096
  • 《插秧诗》契此和尚

    《插秧诗》契此和尚 手把青秧插满田,低头便见水中天。 六根清净方为道,退步原来是向前。 posted @2022-08-04 09:17 郑瀚Andrew 阅读(152 ) 评论(…

    技术杂谈 2023年5月31日
    094
  • ACVFofARMA(1,1)

    [X_{t} – \phi X_{t-1} = Z_{t} + \theta Z_{t-1} ] where (|\phi| < 1) and (\left{ Z…

    技术杂谈 2023年7月24日
    078
  • Linux 学习笔记(一)

    Linux学习笔记(一) 1.1Linux的文件权限 Linux一般将文件的可读写身份分为三个类别:拥有者(owner)、所属群组(group)、其他人(others),并且三种身…

    技术杂谈 2023年6月21日
    097
  • 国产化之Arm64 CPU+银河麒麟系统安装.NetCore

    背景 某个项目需要实现基础软件全部国产化,其中操作系统指定银河麒麟,银河麒麟就是一个Linux发行版,数据库使用达梦V8,这个数据库很多概念和Oracle相似,CPU平台的范围:龙…

    技术杂谈 2023年7月11日
    073
  • thymeleaf在不同session,request作用域的使用

    参考: https://blog.csdn.net/weixin_59668801/article/details/124421911 Original: https://www….

    技术杂谈 2023年7月24日
    092
  • 更安全的rm命令,保护重要数据

    更安全的rm命令,保护重要数据 网上流传的安全的rm,几乎都是提供一个rm的”垃圾”回收站,在服务器环境上来说,这实非良方。 我想,提供一个安全的rm去保护…

    技术杂谈 2023年5月31日
    086
  • DAX :【翻译】自动存在(auto-exist)

    自动存在是 DAX 中内置的一项技术,其唯一的目标是避免无用计算,换句话说,它是 DAX 的过滤机制使用的一种优化技术,目的是减少计算值的工作量。 例如,假设有人构建了一份按大陆和…

    技术杂谈 2023年5月31日
    0105
  • static关键字的一些使用

    百度百科定义static关键字 通常情况下,类成员必须通过它的类的对象访问,但是可以创建这样一个成员,它能够被它自己使用,而不必引用特定的实例。在成员的声明前面加上关键字stati…

    技术杂谈 2023年7月25日
    071
  • 方法是什么

    什么是方法? System.out.println(),这是方法,输出语句的方法 这句语句就是调用系统System类中的标准输出对象out中的println()方法。 (类+对象+…

    技术杂谈 2023年6月21日
    0127
  • FlinkSQL之Windowing TVF

    Windowing TVF 在Flink1.13版本之后出现的替代之前的Group window的产物,官网描述其 is more powerful and effective s…

    技术杂谈 2023年7月24日
    064
  • PYTORCH: 60分钟 | TORCH.AUTOGRAD

    torch.autograd 是PyTorch的自动微分引擎,用以推动神经网络训练。在本节,你将会对autograd如何帮助神经网络训练的概念有所理解。 背景 神经网络(NNs)是…

    技术杂谈 2023年7月25日
    096
  • 利他利己?自利利他?

    利他、利己从来就是一个大问题,但大多数人不是纠结单选题,而是排序题,到底先利己还是先利他? 学佛讲究的是自利利他,因为你连自己都度不了,何谈度众生?我们需要榜样需要以身作则。 可团…

    技术杂谈 2023年5月31日
    097
  • Excel中*替换为空

    查找输入~*替换不输入全部替换将 * 这个替换成空白 Original: https://www.cnblogs.com/gisoracle/p/16309234.htmlAuth…

    技术杂谈 2023年5月30日
    0101
  • 我的笔记本电脑瞬间扩大一个T的容量!

    前言 不知道有多少人在家里搭建中央存储设备的,也就是NAS。这个东西在我日常生活中,存储了大量的个人资料,家人们的照片,技术的资料,还有各种高清影视剧。搭配公网的IP,可以真正做到…

    技术杂谈 2023年7月11日
    0200
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球