一种基于数据库+模板渲染的代码生成器——简介及基础查询
什么要编写代码生成器
在《程序员修炼之道-从小工到专家》第二章节部分,提到一种强加的重复,如项目标准要求含有重复信息的文档,或重复代码中信息的文档,书中建议通过信息存放在一处,通过代码生成器等方式生成其他重复数据,以遵守DRY原则;在这本书的第三站基本工具一节,作者提倡“编写能编写代码的代码”:Write Code That Writes Code。按照作者的划分,代码生成器分为被动代码生成器与主动代码生成器。被动代码生成器即参数化模板,例如创建源文件、编程语言之间的一次性转换、生成查找表及其他在运行时计算很昂贵的资源(如三角函数值表)。主动代码生成器可以理解为某项知识的一种表现形式,每次需要其结果时执行,如根据数据库scheme生成代码源码。
DRY原则:Don’t Repeat Yourself。不要重复你自己
区分被动/主动的问题并不重要,重要的是提醒自己可以通过代码生成器的减少重复度高的工作,将这些工作自动化、标准化,节省有限的时间,提高工作效率。
同样的,在《程序员职业规划之道》一书中,其作者也推荐使用编写代码生成器的方式,尽可能的将工作自动化。
代码生成器的实现思路
在笔者有限的工作年限内,最常见的代码生成器有:
根据数据库表结构生成对应的语言源代码文件;
工作后使用的第一个Web框架是Jfinal,其中最常用的代码生成器为
com.jfinal.plugin.activerecord.generator.Generator
,根据数据库生成程序中使用的Model
低层对象,包括Model
与BaseModel
。根据样式组件生成前端源码文件
如下图,该网站据说是可以实现拖动组件后将页面转换为html代码文件。
一种普遍的基于数据库与渲染模板的代码生成器实现思路
这一思路是个人在学习一个开源框架——若依管理系统时学到的,其系统中的“系统工具——代码生成”可以根据数据库表、表结构生成一整套的前后端代码,包括后端实体类,Mapper类,Service接口与实现,增删改查相关接口以及相应的mybatis-XML文件,前端的样式页面以及接口请求文件等。在项目有快速开发的时候,这一套代码生成器可以极大的减轻工作量。
下图为若依系统代码生成器代码预览截图。
以Java为例,生成器实现步骤大致分为以下几步:
- 通过SQL查询获取数据库表结构,列信息等;
- 将数据库结构映射为编程语言对象,本例即为Java中的对象;
- 配置各个功能版块的模板文件,比如可以使用freemaker,Apache Velocity等模板引擎;
- 渲染模板,依次输出文件
本篇暂且介绍第一步内容。
那么,见惯了CRUD的执行语句的你们,知道如何查询数据库中的表结构信息吗?
一个特殊的数据库:information_schema
通过查询mysql数据库中的表信息涉及到一个特殊的数据库:information_schema
,我们可以通过它来获取所连接的数据库的基础信息。
information_schema
中存储了一些什么信息呢?同样的,我们也需要通过information_schema
来获取:
执行以下SQL:
1 | SELECT * FROM information_schema.`TABLES` |
比如在笔者本地数据库,查询结果如下:
可以看到,其中罗列了本地数据库连接中的所有数据库的表信息,包括数据库名称TABLE_SCHEMA
,表名TABLE_NAME
,数据库引擎ENGINE
,表的数据库行数TABLE_ROWS
等等。
我们在学习数据库的时候也一定学习过下面的语句:
1 | SELECT DATABASE() |
在我们打开的数据库中执行后,截图如下:
由此,我们可以通过下面的语句查询所在数据库的所有表信息:
1 | SELECT * FROM information_schema.`TABLES` WHERE TABLE_SCHEMA = (SELECT DATABASE()) |
表信息有了,列信息在哪呢?
我们查看information_schema
数据库,可以看到有一个表为COLUMNS
,我们来看一下它存储了什么信息:
1 | SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = (SELECT DATABASE()) |
执行结果如下:
其中,我们可以清晰的看到表的所有列名信息COLUMN_NAME
,列的数据类型DATA_TYPE
、COLUMN_TYPE
,以及列的注释信息COLUMN_COMMENT
。
如此,我们便获取了数据库中所有的表的信息以及其列结构信息。
在若依系统中,其作者将第一步“SQL查询数据库结构”分为了两步,第一步,先将数据库结构查询出来,第二步,将这些信息另外存储在单独的表中。这样做的原因主要是在预览/生成时,可以减少系统一步操作的负载压力,并且数据库结构的变动本来也较少,将其查询“缓存”出来是一个不错的技巧。
总结
在人工智能逐渐发展的今天,随着各个领域业务的逐步完善与统一,大量的开发程序员或许或转型为AI维护程序员,代码生成器维护程序员…
接下去的文章,笔者会继续介绍如何从查询出的数据库表结构信息逐步生成所需要的代码的。