简单java代码生成器的开发教程(一),根据数据库表逆向工程生成实体类(附源码)

简单java代码生成器的开发教程(一),根据数据库表逆向工程生成实体类(附源码)以前开发过完整的快速开发平台,想分享里面的基本代码生成的开发流程,大概就两个重点,以前开发过完整的快速开发平台,想分享里面的基本代码生成的开发流程,大概就两个重点,一代码生成引擎,二是编写模版代码生成器的核心开发流程1.如何连接数据库,获取数据库信息,以及根据数据库的表字段信息如何转换成java实体类型1)获取数据库表信息2)数据库表信息转java类型2.配置必须的基本数据,根据模版语言编写代码模版,根据模版生成代码文件(我这里用freemarker模版语言)

大家好,又见面了,我是你们的朋友全栈君。

简单java代码生成器的开发流程(一),根据数据库表逆向工程生成实体类

以前开发过完整的快速开发平台,想分享里面的基本代码生成的开发流程,大概就两个重点,一代码生成引擎,二是编写模版

代码生成器的核心开发流程

  1. 如何连接数据库,获取数据库信息,以及根据数据库的表字段信息如何转换成java实体类型
    1)获取数据库表信息
    2)数据库表信息转java类型
  2. 配置必须的基本数据,根据模版语言编写代码模版,根据模版生成代码文件(我这里用freemarker模版语言)
    1)配置数据库类型,帐号,密码,需要生成的表的基本信息
    2)编写模版,根据配置的信息注入模版生成代码文件以及生成代码文件的路径

开发流程

根据数据库表信息转成java实体类

1. 获取数据库表的基本信息,核心代码

   /** * 根据表名获取该表的所有字段信息 * @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;
}
  1. 表字段类型转java数据类型,上面获取到表信息了,里面的this.getTypeConvert().processTypeConvert(tbfrField.getType())就是将数据库表类型转成java类型,
    详细一点的可以参考下面这篇文章
    总结java数据类型和mysql、oracle、pgsql数据类型对应关系https://blog.csdn.net/qq_21187515/article/details/91495237
    核心代码如下
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;
}
}

用freemarker模版语言进行编写的模版

  1. 生成文件之前获取配置信息存到Map变量,之后注入模版生成代码文件
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;
}
  1. 编写生成实体的模版,模板在resources/template目录下,可以根据需要自行修改
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>
}
  1. 得到代码生成的文件路径
/** * 获取代码生成的文件路径 * @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();
}
  1. 把配置数据注入模版,生成代码文件
  /** * 把配置数据注入模版,生成代码文件 * @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();
}

设置全局的配置 、数据库配置,执行generateToFile()方法生成代码文件

   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&amp;characterEncoding=UTF-8&amp;&useSSL=false");
dsc.setUsername("root");
dsc.setPassword("root");
CodeGenerate codeGenerate = new CodeGenerate(globalConfig,dsc);
//生成代码
codeGenerate.generateToFile();
}

执行完codeGenerate.generateToFile()后可以看到已经把表pre_score、pre_student生成了实体类代码文件
在这里插入图片描述
生成的Sorce.java文件内容:
简单java代码生成器的开发教程(一),根据数据库表逆向工程生成实体类(附源码)

代码生成器源码:https://gitee.com/zhangxinlin/code-generate

简单java代码生成器的开发教程(二),生成springboot+mybatis-plus的增删查改的基本代码(开发利器,附源码)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/144884.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 服务器资源监控工具—nmon

    服务器资源监控工具—nmon      在性能测试过程中,对服务端的各项资源使用情况进行监控是很重要的。对于监控服务器资源的工具nmon是最好不过了。      nmon不仅可以监控内存使用情况、磁盘适配器、文件系统中的可用空间、CPU使用率、页面空间和页面速度、异步I/O(仅适用于AIX)、网络文件系统(NFS)、磁盘I/O速度和读写比率、服务器详细信息和资源、内核统计信息、消耗资源进程、运行队列信息等。而且它资源…

  • go get 使用代理

    go get 使用代理众所周知的原因,goget命令在提取一些工程或依赖时(如golang.org域名)被墙掉。通过使用vpn或代理的方法可以解决。买VPN这个就不多说了,买vpn,相当于直接连接。使用代理通过shell环境变量exporthttp_proxy=http://ip:portgogetgolang.org/xxx通过设置git代理这也是go官方指导。gitconfig–globalhttp.

  • 算法学习路线总结

    算法学习路线总结1.基础算法总结点击就可以查看相关博客文档讲解CreatedwithRaphaël2.2.0基础算法排序、查找算法选择排序冒泡排序插入排序

  • 获取不同长度的UUID[通俗易懂]

    获取不同长度的UUID[通俗易懂]在公司,有时候让处理一些命名规则时,要使用一个唯一标识,还是十六进制的,需要多少位看领导心情.怎么做呢?你别说用随机产生组合的方法啊?虽然那个可行,但是我觉得难受.知道有UUID这个玩意儿之后,那就好办了.UUID含义是通用唯一识别码(UniversallyUniqueIdentifier),这是一个软件建构的标准,也是被开源软件基金会(OpenSoftwareFoundatio

  • axios 跨域问题_前端跨域产生的原因和解决方法

    axios 跨域问题_前端跨域产生的原因和解决方法首先,经典报错:No‘Access-Control-Allow-Origin’解决方法:一、配置main.js此处已经默认请求都添加/api为前缀importVuefrom’vue’importAppfrom’./App.vue’importrouterfrom’./router’importaxiosfrom’axios’import’font-awesome/css/font-awesome.min.css’Vue.config.product

  • EXPORT_SYMBOL使用

    EXPORT_SYMBOL使用EXPORT_SYMBOL只出现在2.6内核中,在2.4内核默认的非static函数和变量都会自动导入到kernel空间的,都不用EXPORT_SYMBOL()做标记的。2.6就必须用EXPO

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号