Java逆向工程(数据库表生成java类)
说起来倒是挺简单的,就是听着名字感觉挺高大上。逆向工程方式有很多,比如mybatis就提供了一个这样的工具mybatis-genderator,这个我反正是没用过只是听说过,以前在公司都是用公司写好的的工具,最近也是闲的无聊自己动手写了一个。
我的这个工程师基于spring和mybatis写的,有兴趣的加上spring-mvc,加个页面也是不错的。
其实呢使用mybatis做逆向工程很简单就是两个select查询就好了,数据库底子好的童鞋们应该记得一下这两个查询语句的(不记得也没关系,可以学嘛):
1. 查询库中的所有表: select * from information_schema.TABLES where TABLE_SCHEMA=(select database())
2.查询表中的所有字段信息: select * from information_schema.COLUMNS where TABLE_SCHEMA = (select database()) and TABLE_NAME=#{tableName}
对于第一条sql来说查询那个库就连接哪个就行了,不需要传参数。但是第二条sql需要将表名传进去的(这也是无可厚非的)
必不可少的我们是需要数据库的4大连接参数,凡是和数据库挂钩应该都需要这几个玩意(这声明一下我这里是用的MySQL)。其他的配置文件上的事情我就不多说了。今天重点不在这里
接下来简单的将dao、service层贴出来了,和平时的web结构一样很简单。
service层
service实现类
接下来就是今天的重点了。其实也很简单,可能很多人都已经想到了,我们都已经获取到了表字段信息了,那么我们只需要一个文件流不就可以了?(嗯,没错,大兄弟,反正我就是这么写的)
其实我的这个很简单,主要围绕一个stringbuffer进行,先拼接到字符串中,然后用流写到文件中。下边我粘一下我的代码吧。
package com.ml.code.one.codegenerator.util; import com.ml.code.one.codegenerator.myservice.MyCodeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.Map; @Component public class CodeGenerator { @Autowired private MyCodeService service; public void codeGenerator(String tableName,String path){ List<Map> columns = service.listColumn(tableName);//查询所有的表字段信息 String className = getClassName(tableName); StringBuffer sb = new StringBuffer(); sb.append("package "+getPackageName(path)+";\n"); sb.append("import java.io.Serializable;"+"\n"); sb.append("import java.util.*;\n"); sb.append("import java.lang.*;\n"); sb.append("import lombok.Data;\n"); sb.append("import lombok.ToString;\n\n"); sb.append("@Data\n@ToString\n"); sb.append("public class "+className+" implements Serializable {\n"); sb.append("\tprivate static final long serialVersionUID = 1L;\n\n"); //获取字段信息 Iterator<Map> iterator = columns.iterator(); while (iterator.hasNext()){ Map next = iterator.next(); Object dataType = next.get("DATA_TYPE");//获取数据类型 String type = classCast(dataType);//数据类型 Object property = next.get("COLUMN_NAME");//获取字段名称 String propertity = getPropertity(property);//属性名称 Object annotation = next.get("COLUMN_COMMENT");//注解 sb.append("\tprivate "+type+" "+propertity+";"+"//"+(String)annotation+"\n"); } sb.append("}"); //拼接结束 //生成文件 try { //生成java文件 getFile(className,sb.toString(),path); //生成mapper.xml // getMapperFile(className,path); } catch (IOException e) { e.printStackTrace(); } } /** * 生成类名 * @param tableName 表名 * @return */ private String getClassName(String tableName){ String newClassName=""; int i = tableName.indexOf("_"); if (i<0){//没有下划线 newClassName = tableName.substring(0, 1).toUpperCase() + tableName.substring(1)+"Po"; }else{//有下划线 String[] strs = tableName.split("_"); StringBuffer sb = new StringBuffer(); for (int m = 0; m<strs.length; m++){ sb.append(strs[m].substring(0, 1).toUpperCase() + strs[m].substring(1)); } newClassName=sb.toString()+"Po"; } return newClassName; } //生成属性java类型 private String classCast(Object obj){ String type=""; String str=(String)obj; if (str.equals("varchar")||str.equals("char")||str.equals("text")){ type="String"; }else if (str.equals("int")){ type="Integer"; }else if (str.equals("bigint")){ type="Long"; }else if (str.equals("double")||str.equals("float")){ type="Double"; }else if (str.equals("date")||str.equals("datetime")||str.equals("timestamp")){ type="Date"; }else { type="String"; } return type; } //数据库字段名字转java属性名字 private String getPropertity(Object obj){ String pro=""; String colum=(String)obj; int index = colum.indexOf("_");//判断是否存在下划线 if (index<0){//没有下划线 pro=colum.substring(0,1).toLowerCase()+colum.substring(1);//首字母小写 }else {//有下划线 StringBuilder sb = new StringBuilder(); String[] colums = colum.split("_"); for (int i = 0; i<colums.length; i++){ if (i==0){ sb.append(colums[i].substring(0,1).toLowerCase()+colums[i].substring(1));//拼接第一个,并将首字母小写 }else{ sb.append(colums[i].substring(0,1).toUpperCase()+colums[i].substring(1));//除了第一个都将首字母大写 } } pro=sb.toString(); } return pro; } /** * 生成包名 */ private String getPackageName(String path){ int index = path.indexOf("java\\"); String newPackage=""; if (index>0){ String substring = path.substring(index+5); newPackage = substring.replace("\\", "."); } return newPackage; } /** * 生成文件 * @param fileName 文件名 * @param info 要写入的内容 * @throws IOException */ private void getFile(String fileName,String info,String path) throws IOException { //生成文件 File file = new File(path+"\\"+fileName+".java"); if (!file.exists()){ file.createNewFile(); } FileWriter writer = new FileWriter(file); writer.write(info); writer.flush(); writer.close(); } /** * 生成Mapper.xml * @param poName */ private void getMapperFile(String poName,String path) throws IOException { //获取文件名 StringBuilder fileName = new StringBuilder(); int index = poName.indexOf("Po"); if (index<0){//没有Po后缀时 fileName.append(poName+"Mapper"); }else{//存在Po后缀 String sub = poName.substring(0, index);//截取到需要的部分 fileName.append(sub+"Mapper"); } //获取路径 StringBuilder newPath = new StringBuilder(); int main = path.indexOf("main\\"); if (main>0){ String substring = path.substring(0, main+5); newPath.append(substring).append("\\resources\\mapper\\"); } File file = new File(newPath+fileName.toString()+".xml"); StringBuilder xmlInfo = new StringBuilder(); xmlInfo.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); xmlInfo.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \n" + " \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n"); xmlInfo.append("<mapper namespace=\"\">\n"); xmlInfo.append("\n\n"); xmlInfo.append("</mapper>"); FileWriter fw = new FileWriter(file); fw.write(xmlInfo.toString()); fw.flush(); fw.close(); } }
这里我用的是boot工程写的,运行的时候我选择用boot自带的test工具运行就ok了(别忘了在启动类上加上dao层的包扫描呦)
到这里呢这个简单的逆向工程就结束了,这个可以直接生成到你指定文件下,顺带连Mapper.xml也生成了的。大佬勿喷。
有需要源码的可以到以下网盘获取,(网盘中的也只是一部分,只是逆向工程部分,其他的需要你们自行补充,应该是不难的)
补充一下,如果有用idea的我建议用idea的代码生成工具哈 下载一个插件就可以了 EasyCode,至于使用方法很简单,把你的idea连上数据库就好了,而且还可以手动配置呢
链接:https://pan.baidu.com/s/1KW7h9vro2U199hsL85Q38w
提取码:obpf