大家好,我是轩脉刃。

我们写业务的时候和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. Node.js 模块之【passport】

    什么是passport passport是Nodejs的一个中间键,用于用户名和密码的验证登陆.在项目中我用它来验证后台用户名和密码,但passport更多用在第三方登录,功能强大. 安装与配置 本项 ...

  2. SQL高级优化(四)之SQL优化

    SQL优化 一.SQL优化简介 解释:对于特定的要求,使用更有的SQL策略或索引策略,以达到让结果呈现的时间更短,从而提升操作效率的过程就是SQL优化. SQL优化包含在数据库级别优化中.我们平常所说 ...

  3. MongoDB之几种情况下的索引选择策略

    一.MongoDB如何选择索引 如果我们在Collection建了5个index,那么当我们查询的时候,MongoDB会根据查询语句的筛选条件.sort排序等来定位可以使用的index作为候选索引:然 ...

  4. vmware快速扩容虚拟磁盘

    在使用vmware进行虚拟化的时候,会遇到虚拟磁盘不够用的情况,以前的办法都是使用lvm进行管理扩容,目前在linux上可以实现快速扩容了,具体方法如下: 该方法参考阿里云在线扩容文档:文档地址 其中 ...

  5. Android EditText不弹出输入法总结,焦点问题的总结

    看一个manifest中Activity的配置,如果这个页面有EditText,并且我们想要进入这个页面的时候默认弹出输入法,可以这样设置这个属相:android:windowSoftInputMod ...

  6. C# 基本控件使用练习

    自己设计并编写一个 Windows 应用程序,要求用到 TextBox.GroupBox.RadioButton.CheckBox.ComboBox.ListBox 控件. 代码如下: 页面1: us ...

  7. bom中的offset,client,scroll

    简单明了

  8. 集合框架-Map集合-LinkedHashMap及关联源码操作

    1 package cn.itcast.p9.linkedhashmap.demo; 2 3 import java.util.HashMap; 4 import java.util.Iterator ...

  9. centos下python2升级为python3

    1.下载 下载地址 https://www.python.org/downloads/release/python-353/ 选择"Gzipped source tarball"这 ...

  10. Linux下安装confluence汉化破解版

    Atlassian Confluence(简称Confluence)是一个专业的wiki程序.它是一个知识管理的工具,通过它可以实现团队成员之间的协作和知识共享.Confluence 不是一个开源软件 ...