一种基于数据库+模板渲染的代码生成器——表结构暂存与类设计
接上篇
在上一篇文章《一种基于数据库+模板渲染的代码生成器——简介及数据库查询》中,我们介绍了代码生成器的基本概念以及常见的几种代码生成器,并阐述了通过mysql数据库中的information_schema
库,查询数据库中的表结构、列结构等信息的方法。
本篇文章将继续阐述,查询出表结构与列结构后,如何将其逐步映射为编程语言Java中的类。
表与列结构暂存
在若依系统中,其实现代码生成分为两个步骤,第一步被称为“导入表”,即将所要生成代码的表的结构信息存储到到某几个指定表gen_table
、gen_table_column
中;之后再通过表中的数据渲染内容。
gen_table
、gen_table_column
其注释分别为:
表名 | 注释 |
---|---|
gen_table | 代码生成业务表 |
gen_table_column | 代码生成业务表字段 |
先来看一下gen_table
存储了哪些信息:
执行以下SQL:
SELECT
COLUMN_NAME,
COLUMN_COMMENT,
DATA_TYPE
FROM
information_schema.`COLUMNS`
WHERE
TABLE_NAME = 'gen_table'
AND TABLE_SCHEMA = 'ry-vue'
查询结果如下图:
再来看gen_table_column
:
SELECT
COLUMN_NAME,
COLUMN_COMMENT,
DATA_TYPE
FROM
information_schema.`COLUMNS`
WHERE
TABLE_NAME = 'gen_table_column'
AND TABLE_SCHEMA = 'ry-vue'
执行结果如下:
在Java中,分别按照表gen_table
,gen_table_column
构建两个实体对象,即Entity,以便后续通过mybatis等对其进行保存等相关操作。
我们截图部分源码代码(其所属位置位于若依项目:ruoyi-generator/src/main/java/com/ruoyi/generator/domain路径下):
public class GenTable extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 编号 */
private Long tableId;
/** 表名称 */
@NotBlank(message = "表名称不能为空")
private String tableName;
/** 表描述 */
@NotBlank(message = "表描述不能为空")
private String tableComment;
/** 关联父表的表名 */
private String subTableName;
}
public class GenTableColumn extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 编号 */
private Long columnId;
/** 归属表编号 */
private Long tableId;
/** 列名称 */
private String columnName;
/** 列描述 */
private String columnComment;
}
表名列名与类名字段名的转换
在获取到表结构与列结构数据后,其名称大多数是不符合类名创建规则的,需要做一个额外的转换,如下图:
表名与列名 | Java类名与字段名 |
---|---|
表名:sys_my_user | MyUser |
列名:user_name | userName |
对于列名,将其转换为驼峰命名法;对于表名,一是注意需要去掉某些指定前缀,二是将剩余部分转换为首字母大写的驼峰。
对于转换为驼峰的方式,我在若依系统源码中发现有两个不同的实现方式,供大家参考:
第一种,从字符串开头,通过大写标识依次拼接字符:
/*com.ruoyi.common.utils.StringUtils*/
private static final char SEPARATOR = '_';
/**
* 转换为驼峰命名法
*/
public static String toCamelCase(String s)
{
if (s == null)
{
return null;
}
s = s.toLowerCase();
StringBuilder sb = new StringBuilder(s.length());
boolean upperCase = false;
for (int i = 0; i < s.length(); i++)
{
char c = s.charAt(i);
if (c == SEPARATOR)
{
upperCase = true;
}
else if (upperCase)
{
sb.append(Character.toUpperCase(c));
upperCase = false;
}
else
{
sb.append(c);
}
}
return sb.toString();
}
第二种,按照下划线拆分原始字符串后,依次首字母大小,然后拼接:
/*com.ruoyi.common.utils.StringUtils*/
public static String convertToCamelCase(String name)
{
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty())
{
// 没必要转换
return "";
}
else if (!name.contains("_"))
{
// 不含下划线,仅将首字母大写
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels)
{
// 跳过原始字符串中开头、结尾的下换线或双重下划线
if (camel.isEmpty())
{
continue;
}
// 首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
return result.toString();
}
数据类型的转换
即数据库中定义的数据类型包括:varchar, int, datetime, decimal等等,这些都需要一一映射为Java中的相关对象,包括String, Integer, Date, BigDecimal等等。
暂存结果:
比如我们的表my_user,结构信息如下:
经过转换,存储在gen_table
以及gen_table_column
中的数据为:
总结
我们便可不需要通过information_schema
数据库查询信息,而仅需要通过这两个gen_
表数据生成对应的类信息。通过其存储数据,我们也可以看到,表中存储了构建对象属性的类型、名称,这也便于后续直接生成对象,而不需要再次将其转换,减轻了一步操作的系统压力。
通过使用表“缓存”数据结构,的确是十分高明的方法,值得学习!
后续
那么又如何通过gen_table
、gen_table_column
中的数据生成想要的文件呢?我们之后会一一介绍。
- 点赞
- 收藏
- 关注作者
评论(0)