代码生成器原理很简单,用一句话概括就是:将数据库字段转换成Java字段并输出内容。
如下图所示:
![code-gen.png 输入图片说明]()
因此,首先需要做的是获取表信息以及表的字段信息,一般有两种方式,第一种:连接到数据库,执行相关SQL,查询出表结构信息。第二种:解析DDL,得到相关信息,code-gen采用第一种做法。
包括表名称,表备注,Mysql可以使用下面这个SQL。(code-gen源码对应:com.gitee.gen.gen.mysql.MySqlTableSelector)
SHOW TABLE STATUS FROM table_name
如果需要指定某张表,直接加where条件即可
SHOW TABLE STATUS FROM table_name where name = 'user_info';
查询后结果如下:
| Name |
Engine |
Version |
Row_format |
Rows |
Avg_row_length |
Data_length |
Max_data_length |
Index_length |
Data_free |
Auto_increment |
Create_time |
Update_time |
Check_time |
Collation |
Checksum |
Create_options |
Comment |
| "user_info" |
"InnoDB" |
"10" |
"Dynamic" |
"0" |
"0" |
"16384" |
"0" |
"0" |
"0" |
"1" |
"2020-12-22 15:16:40" |
|
|
"utf8_general_ci" |
|
|
"用户信息表" |
Mysql可以用如下SQL(code-gen对应源码:com.gitee.gen.gen.mysql.MySqlColumnSelector):
SHOW FULL COLUMNS FROM user_info;
查询后结果如下:
| Field |
Type |
Collation |
Null |
Key |
Default |
Extra |
Privileges |
Comment |
| "id" |
"int(11)" |
|
"NO" |
"PRI" |
|
"auto_increment" |
"select,insert,update,references" |
"自增主键" |
| "name" |
"int(11)" |
|
"NO" |
|
|
|
"select,insert,update,references" |
"姓名" |
| "create_time" |
"timestamp" |
|
"NO" |
|
"CURRENT_TIMESTAMP" |
|
"select,insert,update,references" |
"添加时间" |
从表格中,可以获取字段名称、类型、备注、是否主键、是否自增
查询出数据库的基本信息后,把这信息放到对象中,方便后续处理。
/**
* 数据库表定义,从这里可以获取表名,字段信息
*/
public class TableDefinition {
/**
* 表名
*/
private String tableName;
/**
* 表注释
*/
private String comment;
/**
* 字段
*/
private List<ColumnDefinition> columnDefinitions
... 省略 getter setter
}
其中TableDefinition类存放表信息,ColumnDefinition类存放字段信息
接下来是将TableDefinition对象中的变量绑定到Velocity模板当中去。
VelocityContext context = new VelocityContext();
TableDefinition tableDefinition = ...
context.put("table", tableDefinition);
context.put("columns", tableDefinition.getColumnDefinitions());
return VelocityUtil.generate(context, template);
VelocityContext存放Velocity变量,在对象中放入两个变量table、columns,template是模板内容
然后再模板中就可以使用对应的变量了,对应的模板可以这么写:
/**
* ${table.comment}
*/
public class ${context.javaBeanName} {
// Java字段信息
#foreach($column in $columns)
/** ${column.comment} */
private ${column.javaTypeBox} ${column.javaFieldName};
#end
// getter,setter部分
#foreach(${column} in ${columns})
public void set${column.javaFieldNameUF}(${column.javaTypeBox} ${column.javaFieldName}) {
this.${column.javaFieldName} = ${column.javaFieldName};
}
public ${column.javaTypeBox} get${column.javaFieldNameUF}() {
return this.${column.javaFieldName};
}
#end
}
得到生成结果后,把内容返回到前端页面。
处理多种数据库
如何处理多种数据库,这里的关键点是要获取数据库的表结构以及字段信息,每种数据库的获取SQL是不一样的,因此需要把获取表信息和获取字段信息抽象出来,然后让实际的数据库取实现抽象部分即可。
code-gen对应抽象类: