The principle of the code generator is very simple. It can be summed up in one sentence: convert database fields into Java fields and output the content.
As shown below:
Therefore, the first thing that needs to be done is to obtain table information and table field information. There are generally two ways. The first is to connect to the database, execute related SQL, and query the table structure information. The second: parsing DDL to get relevant information, code-gen adopts the first method.
- Get table information
Including table name, table remarks, Mysql can use the following SQL. ( code-gen source code corresponds to: com.gitee.gen.gen.mysql.MySqlTableSelector)
SHOW TABLE STATUS FROM table_name
If you need to specify a table, you can directly add the where condition
SHOW TABLE STATUS FROM table_name where name = 'user_info';
The query results are as follows:
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" | "User Information Form" |
- Get table field information
Mysql can use the following SQL ( code-gen corresponding source code: com.gitee.gen.gen.mysql.MySqlColumnSelector):
SHOW FULL COLUMNS FROM user_info;
The query results are as follows:
Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
---|---|---|---|---|---|---|---|---|
"id" | "int(11)" | "NO" | "PRI" | "auto_increment" | "select,insert,update,references" | "Auto Increment Primary Key" | ||
"name" | "int(11)" | "NO" | "select,insert,update,references" | "Name" | ||||
"create_time" | "timestamp" | "NO" | "CURRENT_TIMESTAMP" | "select,insert,update,references" | "add time" |
From the table, you can get the field name, type, remarks, whether it is the primary key, whether it is self-incrementing
After querying the basic information of the database, put this information into the object to facilitate subsequent processing.
/**
* 数据库表定义,从这里可以获取表名,字段信息
*/
public class TableDefinition {
/**
* 表名
*/
private String tableName;
/**
* 表注释
*/
private String comment;
/**
* 字段
*/
private List<ColumnDefinition> columnDefinitions
... 省略 getter setter
}
The TableDefinition
class stores table information, and the ColumnDefinition
class stores field information
The next step is to TableDefinition
bind the variables in the object to the Velocity template.
VelocityContext context = new VelocityContext();
TableDefinition tableDefinition = ...
context.put("table", tableDefinition);
context.put("columns", tableDefinition.getColumnDefinitions());
return VelocityUtil.generate(context, template);
VelocityContext stores Velocity variables, put two variables table and columns in the object, template is the template content
Then you can use the corresponding variables in the template. The corresponding template can be written as follows:
/**
* ${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
}
After getting the generated result, return the content to the front-end page.
Handling multiple databases
How to deal with multiple databases, the key point here is to obtain the table structure and field information of the database. The SQL for each database is different, so it is necessary to abstract the table information and field information, and then let the actual database Take the implementation of the abstract part.
code-gen corresponds to the abstract class:
-
The com.gitee.gen.gen.TableSelector abstract class is used to obtain subclasses of table information:
- com.gitee.gen.gen.mysql.MySqlTableSelector
- com.gitee.gen.gen.oracle.OracleTableSelector
- com.gitee.gen.gen.postgresql.PostgreSqlTableSelector
- com.gitee.gen.gen.sqlserver.SqlServerTableSelector
-
The com.gitee.gen.gen.ColumnSelector abstract class is used to obtain subclasses of table field information:
- com.gitee.gen.gen.mysql.MySqlColumnSelector
- com.gitee.gen.gen.oracle.OracleColumnSelector
- com.gitee.gen.gen.postgresql.PostgreSqlColumnSelector
- com.gitee.gen.gen.sqlserver.SqlServerColumnSelector