大家好,我是轩脉刃。

我们写业务的时候和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的二次封装了。

当然这套函数是基于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%';

最终生成的文件如下:

gen有一些高级的功能:

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

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

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

// 插入一条数据
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
}
// 插入一条数据
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: 必选,表示输出的路径
database: 可选,默认使用database.default

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

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

请选择要生成模型的表格:
[] *
[] users
[] answers
[] questions

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

继续下列操作会在目录(xxxx)生成下列文件:
user.gen.go(覆盖)
answer.gen.go(新文件) 请确认是否继续?(Y/N)

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

请选择模型规则:
[] FieldNullable, 对于数据库的可null字段设置指针
[] FieldCoverable, 根据数据库的Default设置字段的默认值
[] FieldWithIndexTag, 根据数据库的索引关系设置索引标签
[] FieldWithTypeTag, 生成类型字段

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

自动生成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 比较两个数组,获取两个数组交集,仅对基础元素生效
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

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

下一步确认y继续

最后生成模型成功

查看文件,确实生成了model

功能完结。

为hade增加model自动生成功能的更多相关文章

  1. 给dtcms增加模板自动生成功能

    作为dtcms的使用者你是不是像我一样,也在不停的修改模板之后要点击生成模板浪费了很多开发模板的时间? 那就跟我一起给dtcms增加一个开发者模式,当模板修改完成之后,直接刷新页面就能看到效果,而不再 ...

  2. Markdown 中的目录自动生成功能 TOC

    目录 Markdown 中的目录自动生成功能 TOC 1. 标题一 1.1 标题二 1.标题二 2. 标题一 2.1 标题二 2.2 标题二 Markdown 中的目录自动生成功能 TOC 1. 标题 ...

  3. 使用automake等命令自动生成Makefile文件 (转载)

    使用automake等命令自动生成Makefile文件   Linux下编程时,为了方便编译,往往使用Makefile文件自动完成编译,但是Makefile文件本身的书写十分复杂,规则很多.好在Lin ...

  4. 【Golang】 可以自动生成测试用例的库--gotests

    简介 gotests是一个Golang命令行工具,它可以使编写Go的测试代码变得容易.它能基于目标源文件的函数和方法生成数据驱动测试用例,并且在此过程会自动导入任何依赖. 下面是gotests在使用S ...

  5. Mybatis 如何自动生成bean dao xml 配置文件 generatorconfig.xml (main()方法自动生成更快捷)

    最近项目要用到mybatis中间件,中间涉及到要对表结构生成bean,dao,和sqlconfig.xml 所以记录一下学习过程 首先是准备工作,即准备需要的jar包:我们的数据库mysql,所以驱动 ...

  6. 痞子衡嵌入式:MCUXpresso IDE下工程链接文件配置管理与自动生成机制

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下工程链接文件配置管理与自动生成机制. 痞子衡在 2018 年初写过一个专题 <嵌入式开发文件系列&g ...

  7. spring和mybatis集成,自动生成model、mapper,增加mybatis分页功能

    软件简介 Spring是一个流行的控制反转(IoC)和面向切面(AOP)的容器框架,在java webapp开发中使用广泛.http://projects.spring.io/spring-frame ...

  8. springboot和mybatis集成,自动生成model、mapper,增加mybatis分页功能

    整体思路和http://www.cnblogs.com/mahuan2/p/5859921.html相同. 主要讲maven的pom.xml和一些配置变化,详细说明. 软件简介 Spring是一个流行 ...

  9. idea使用generator自动生成model、mapper、mapper.xml(转)

    原文链接:http://www.mamicode.com/info-detail-445217.html TEP 0.在Intellij IDEA创建maven项目(本过程比较简单,略) STEP 1 ...

随机推荐

  1. Flask_generate_password_hash的加盐哈希加密算法与check_password_hash的校验

    密码加密简介 密码存储的主要形式: 明文存储:肉眼就可以识别,没有任何安全性. 加密存储:通过一定的变换形式,使得密码原文不易被识别. 密码加密的几类方式: 明文转码加密算法:BASE64, 7BIT ...

  2. spring boot + redis --- 心得

    1.前言 习惯使用springMVC 配置 redis ,现在使用spring boot ,得好好总结怎么在spring boot 配置和使用 ,区别真的挺大的. 2.环境 spring boot  ...

  3. c#多进程通讯,今天,它来了

    引言 在c#中,可能大多数人针对于多线程之间的通讯,是熟能生巧,对于AsyncLocal 和ThreadLocal以及各个静态类中支持线程之间传递的GetData和SetData方法都是信手拈来,那多 ...

  4. Python多线程、线程池及实际运用

    我们在写python爬虫的过程中,对于大量数据的抓取总是希望能获得更高的速度和效率,但由于网络请求的延迟.IO的限制,单线程的运行总是不能让人满意.因此有了多线程.异步协程等技术. 下面介绍一下pyt ...

  5. Three.js 实现虎年春节3D创意页面

    背景 虎年 春节将至,本文使用 React + Three.js 技术栈,实现趣味 3D 创意页面.本文包含的知识点主要包括:ShadowMaterial. MeshPhongMaterial 两种基 ...

  6. 同步gitlab与github

    1.找到setting 2.找到左下方的developer setting 3.按标好的数字依次执行 4.填写note并勾选repo 5.在最左下方勾选 6.保存生成的新的token到其他地方,之后你 ...

  7. Cesium中级教程5 - Terrain 地形

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ CesiumJS支持对与水流相关的海洋.湖泊和河流以及全球高分辨 ...

  8. CMake语法—普通变量与函数(Normal Variable And Function)

    目录 CMake语法-普通变量与函数(Normal Variable And Function) 1 CMake普通变量与函数示例 1.1 CMakeLists.txt 1.2 执行CMake配置脚本 ...

  9. 带你十天轻松搞定 Go 微服务系列(二)

    上篇文章开始,我们通过一个系列文章跟大家详细展示一个 go-zero 微服务示例,整个系列分十篇文章,目录结构如下: 环境搭建 服务拆分(本文) 用户服务 产品服务 订单服务 支付服务 RPC 服务 ...

  10. Qt之QColorDialog

    widget.h: #ifndef WIDGET_H #define WIDGET_H #include <QWidget> class Widget : public QWidget { ...