以前开发过完整的快速开发平台,想分享里面的基本代码生成的开发流程,大概就两个重点,一代码生成引擎,二是编写模版
代码生成器的核心开发流程
/**
* 根据表名获取该表的所有字段信息
* @param tableName 表名称
* @return
*/
public List<TableField> getTbfrFields(String tableName){
List<TableField> tbColumns = new ArrayList();
//与数据库的连接
Connection conn = getConn();
Statement stm = null;
ResultSet rs = null;
try {
stm = conn.createStatement();
ResultSet rsKey = conn.getMetaData().getPrimaryKeys(null,null,tableName.toUpperCase());
String keyName=null;
while(rsKey.next()){
keyName = rsKey.getString("COLUMN_NAME").toLowerCase();
keyName = CommonUtils.getNoUnderlineStr(keyName);
}
rs = conn.getMetaData().getColumns( null, getSchema(conn),tableName.toUpperCase(), "%");
while(rs.next()){
TableField tbfrField = new TableField();
String fieldNm = rs.getString("COLUMN_NAME").toLowerCase();
tbfrField.setName(fieldNm);//表字段名
tbfrField.setPropertyName(CommonUtils.getNoUnderlineStr(fieldNm));//字段名
tbfrField.setComment(rs.getString("REMARKS"));//字段注释
tbfrField.setType(rs.getString("TYPE_NAME"));//字段类型
tbfrField.setColumnType(this.getTypeConvert().processTypeConvert(tbfrField.getType()));
if(keyName!=null && keyName.equals(tbfrField.getName())){
tbfrField.setKeyIdentityFlag(true);
}else{
tbfrField.setKeyIdentityFlag(false);
}
tbColumns.add(tbfrField);
}
if(stm!=null){
stm.close();
}
if(rs!=null){
rs.close();
}
} catch (SQLException e) {
throw new RuntimeException("getColumnNames failure", e);
} catch (Exception e) {
throw new RuntimeException("Exception rs failure", e);
}
return tbColumns;
}
public DbColumnType processTypeConvert(String fieldType) {
String t = fieldType.toLowerCase();
if (!t.contains("char") && !t.contains("text")) {
if (t.contains("bigint")) {
return DbColumnType.LONG;
} else if (t.contains("int")) {
return DbColumnType.INTEGER;
} else if (!t.contains("date") && !t.contains("time") && !t.contains("year")) {
if (t.contains("text")) {
return DbColumnType.STRING;
} else if (t.contains("bit")) {
return DbColumnType.BOOLEAN;
} else if (t.contains("decimal")) {
return DbColumnType.BIG_DECIMAL;
} else if (t.contains("clob")) {
return DbColumnType.CLOB;
} else if (t.contains("blob")) {
return DbColumnType.BLOB;
} else if (t.contains("binary")) {
return DbColumnType.BYTE_ARRAY;
} else if (t.contains("float")) {
return DbColumnType.FLOAT;
} else if (t.contains("double")) {
return DbColumnType.DOUBLE;
} else {
return !t.contains("json") && !t.contains("enum") ? DbColumnType.STRING : DbColumnType.STRING;
}
} else {
return DbColumnType.DATE;
}
} else {
return DbColumnType.STRING;
}
}
public Map<String, Object> execute() {
Map data = new HashMap();
data.put("entityPackage", globalConfig.getEntityPackage());//实体的包名
//移除表前缀,表名之间的下划线,得到实体类型
String entity = CommonUtils.getNoUnderlineStr(CommonUtils.removePrefix(tableInfo.getName().toLowerCase(),globalConfig.getPrefix()));
data.put("entity", entity);//实体名称
data.put("author", globalConfig.getAuthor());//创建作者
data.put("date", CommonUtils.getFormatTime("yyyy-MM-dd", new Date() ));//创建时间
data.put("table", tableInfo);//表信息
// for (TableField field:tableInfo.getFields()) {
// if(field.isKeyIdentityFlag()){//获取主键字段信息
// data.put("tbKey", field.getName());
// data.put("tbKeyType", field.getColumnType());
// break;
// }
// }
return data;
}
package ${entityPackage};
import ${entityPackage}.${entity};
import java.io.Serializable;
/**
* 描述: ${table.comment}
* author: ${author}
* date: ${date}
*/
@TableName("${table.name}")
public class ${entity} implements Serializable {
private static final long serialVersionUID = 1L;
<#-- 循环属性名称 -->
<#list table.fields as field>
<#if field.comment??>
/**
* ${field.comment}
*/
</#if>
<#if field.keyIdentityFlag>
@TableId(value="${field.name}", type= IdType.AUTO)
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
<#-- 循环set/get方法 -->
<#list table.fields as field>
<#if field.propertyType == "Boolean">
<#assign getprefix="is"/>
<#else>
<#assign getprefix="get"/>
</#if>
public ${field.propertyType} ${getprefix}${field.capitalName}() {
return ${field.propertyName};
}
public void set${field.propertyName?cap_first}(${field.propertyType} ${field.propertyName}) {
this.${field.propertyName} = ${field.propertyName};
}
</#list>
}
/**
* 获取代码生成的文件路径
* @param type
* @param entityName
* @return
*/
public String getCodePath(String type, String entityName)
{
StringBuilder path = new StringBuilder();
if (StringUtils.isNotBlank(type)) {
String codeType = Enum.valueOf(CodeType.class, type).toString();
//开头,项目路径
if(StringUtils.isEmpty(this.globalConfig.getOutputDir())){
String projectPath = getProjectPath();//没有设置outputDir的话默认用当前项目resources/code路径下
path.append(projectPath+"src/main/resources/code");//项目名
}else{
path.append(this.globalConfig.getOutputDir());//项目名
}
path.append("/");
if("entity".equals(codeType)){
//包名 package.path
path.append(globalConfig.getEntityPackage());
path.append("/");
//文件名
path.append(StringUtils.capitalize(entityName));
//后缀
path.append(".java");
}else {
//其他类型文件生成
}
} else {
throw new IllegalArgumentException("type is null");
}
return path.toString();
}
/**
* 把配置数据注入模版,生成代码文件
* @param templateFileName
* @param type
* @param data
* @throws TemplateException
* @throws IOException
*/
public void generateFile(String templateFileName, String type, Map data) throws TemplateException,IOException
{
String entityName = data.get("entity").toString();
String fileNamePath = getCodePath(type, entityName);//获取生成的文件路径
System.out.println("fileNamePath:"+fileNamePath);
String fileDir = StringUtils.substringBeforeLast(fileNamePath, "/");
Template template = getConfiguration().getTemplate(templateFileName);//获取模版信息
FileUtils.forceMkdir(new File(fileDir + "/"));
Writer out = new OutputStreamWriter(
new FileOutputStream(fileNamePath), globalConfig.getSystem_encoding());//生成的文件编码
template.process(data, out);//结合模版生成代码文件
out.close();
}
public static void main(String[] args)
{
GlobalConfig globalConfig = new GlobalConfig();//全局配置
globalConfig.setTableNames(new String[]{"pre_score","pre_student"});//需要生成的实体
globalConfig.setPrefix(new String[]{"ali_"});//生成的实体移除前缀
globalConfig.setOutputDir("D://code/");//文件输出路径,不配置的话默认输出当前项目的resources/code目录下
DataSourceConfig dsc = new DataSourceConfig();//数据库配置
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUrl("jdbc:mysql://192.168.33.203:3306/test?useUnicode=true&characterEncoding=UTF-8&&useSSL=false");
dsc.setUsername("root");
dsc.setPassword("root");
CodeGenerate codeGenerate = new CodeGenerate(globalConfig,dsc);
//生成代码
codeGenerate.generateToFile();
}
执行完codeGenerate.generateToFile()后可以看到已经把表pre_score、pre_student生成了实体类代码文件
生成的Sorce.java文件内容:
代码生成器源码:https://gitee.com/zhangxinlin/code-generate
简单java代码生成器的开发教程(二),生成springboot+mybatis-plus的增删查改的基本代码(开发利器,附源码)