新接手一个项目,没有数据库文件,并且Entity实体类放在不同的文件路径中,写了个转换工具,如下:
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.annotations.TableId;
import io.swagger.annotations.ApiModelProperty;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static cn.hutool.core.io.FileUtil.newFile;/*** 根据实体类生成表生成语句*/
@Slf4jclass EntityToTablesUtil {/*** java类型与数据库类型映射*/public static HashMap<String,String> javaPropertyMap = new HashMap<>(16, 1);static {javaPropertyMap.put("integer", " int(8) ");javaPropertyMap.put("int", " int(8) ");javaPropertyMap.put("short", " tinyint(4) ");javaPropertyMap.put("byte", " tinyint(4) ");javaPropertyMap.put("long", " bigint(11) ");javaPropertyMap.put("bigdecimal", " decimal(20,4) ");javaPropertyMap.put("double", " double(10,2) ");javaPropertyMap.put("float", " float(10,2) ");javaPropertyMap.put("boolean", " tinyint(4) ");javaPropertyMap.put("timestamp", " datetime ");javaPropertyMap.put("date", " datetime ");javaPropertyMap.put("localdatetime", " datetime ");javaPropertyMap.put("string", " varchar(255) ");}public static void main(String[] args) {// 生成sql的文件夹String filePath = "E:\\";// 实体类所在的package在磁盘上的绝对路径String packageName1 = "D:\\4.program\\17\\tourdataplatform\\src\\main\\java\\com\\ichinae\\base\\mgr\\data\\entity";// 项目中实体类的路径String prefix1 = "com.ichinae.base.mgr.data.entity.";StringBuilder sqlStr1 = buildSql(packageName1, prefix1);// 实体类所在的package在磁盘上的绝对路径String packageName2 = "D:\\4.program\\17\\tourdataplatform\\src\\main\\java\\com\\ichinae\\base\\mgr\\data\\entity\\datareport";// 项目中实体类的路径String prefix2 = "com.ichinae.base.mgr.data.entity.datareport.";StringBuilder sqlStr2 = buildSql(packageName2, prefix2);// 实体类所在的package在磁盘上的绝对路径String packageName3 = "D:\\4.program\\17\\tourdataplatform\\src\\main\\java\\com\\ichinae\\base\\mgr\\data\\entity\\ticketstatistics\\task";// 项目中实体类的路径String prefix3 = "com.ichinae.base.mgr.data.entity.ticketstatistics.task.";StringBuilder sqlStr3 = buildSql(packageName3, prefix3);assert sqlStr1 != null;sqlStr1.append(sqlStr2).append(sqlStr3);System.out.println(sqlStr1);
// sqlToFile(sqlStr1.toString(), filePath + "work.sql");}private static StringBuilder buildSql(String packageName, String prefix) {StringBuilder sqlStr = new StringBuilder();// 获取包下的所有类名称String className = "";List<String> list = getAllClasses(packageName);if (CollUtil.isEmpty(list)) {return null;}for (String str : list) {try {className = prefix + str.substring(0, str.lastIndexOf("."));String sql = generateSql(className, packageName,str);sqlStr.append("\n ").append(sql);}catch (Exception e) {e.printStackTrace();log.error("错误类:{}", str);}}return sqlStr;}/*** 根据实体类生成建表语句* @param className 全类名*/public static String generateSql(String className,String packPath,String javaName){try {Class<?> clz = Class.forName(className);String className1 = dealSubLine(clz.getSimpleName());//处理classNameclassName = className1.substring(1);//获取表中文名称String tableCommit = getTableName(packPath+"\\"+javaName);String tableCommitVarchar=" COMMENT='"+tableCommit+"';";Field[] fields = clz.getDeclaredFields();StringBuilder column = new StringBuilder();String primaryKey = null;List<String> colList = new ArrayList<>();for (Field f : fields) {String dealName;if(!"serialVersionUID".equals(f.getName())){//获取注解名称String commitVachr = "";ApiModelProperty apiModelProperty = f.getAnnotation(ApiModelProperty.class);if(Objects.nonNull(apiModelProperty)){String filedChineseName = apiModelProperty.value();commitVachr=" COMMENT '"+filedChineseName+"',";}else{commitVachr=" COMMENT '',";}//驼峰转换dealName = dealSubLine(f.getName());if (colList.contains(dealName)) {continue;}String filedTypeName = f.getType().getName();String suffix = filedTypeName.substring(filedTypeName.lastIndexOf(".")+1);if ("List".equals(suffix)) {continue;}String dataType = javaPropertyMap.get(suffix.toLowerCase());if (StringUtils.isBlank(dataType)) {log.error("字段类型为空:{}", suffix);continue;}TableId tableId = f.getAnnotation(TableId.class);if(Objects.nonNull(tableId)){column.append(" \n `").append(dealName).append("`").append(dataType).append("NOT NULL AUTO_INCREMENT").append(commitVachr);primaryKey = dealName;}else {column.append(" \n `").append(dealName).append("`").append(dataType).append(" DEFAULT NULL ").append(commitVachr);}colList.add(dealName);}}return "\n DROP TABLE IF EXISTS `" + className + "`; " +" \n CREATE TABLE `" + className + "` (" + " \n " + column +" \n PRIMARY KEY (`" + primaryKey + "`) " +" \n ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci " +tableCommitVarchar;} catch (ClassNotFoundException e) {log.debug("该类未找到!");return null;}}/*** 获取包下的所有类名称,获取的结果类似于 XXX.java* @param packageName 包路径* @return 类List*/public static List<String> getAllClasses(String packageName){List<String> classList = new ArrayList<>();File f = new File(packageName);if (!f.exists() || !f.isDirectory()) {throw new RuntimeException("包路径未找到!");}File[] files = f.listFiles();assert files != null;for (File file : files) {if (file.isFile()) {classList.add(file.getName());}}log.info("包路径中类有:{}个", classList.size());return classList;}/*** 将string 写入sql文件* @param str sql* @param path sql打印路径*/public static void sqlToFile(String str, String path){byte[] sourceByte = str.getBytes();try {//文件路径(路径+文件名)File file = new File(path);//文件不存在则创建文件,先创建目录if (!file.exists()) {File dir = new File(file.getParent());dir.mkdirs();file.createNewFile();}//文件输出流用于将数据写入文件FileOutputStream outStream = new FileOutputStream(file);outStream.write(sourceByte);outStream.flush();//关闭文件输出流outStream.close();System.out.println("生成成功");} catch (Exception e) {e.printStackTrace();}}private static String dealSubLine(String str){//String str = "areaObjectCode";StringBuilder ss = new StringBuilder();char[] charArray = str.toCharArray();for (int i = 0; i < charArray.length; i++) {if (charArray[i] >= 'A' && charArray[i] <= 'Z') {ss.append("_").append(charArray[i]);} else {ss.append(charArray[i]);}}return ss.toString().toLowerCase();}/*** 获取表中文名称*/@SneakyThrowsprivate static String getTableName(String filePath){File f= newFile(filePath);InputStreamReader read= new InputStreamReader( new FileInputStream(f), StandardCharsets.UTF_8);BufferedReader reader= new BufferedReader(read);String line;while((line=reader.readLine())!= null){//判断字符串包含中文切读取中文char[] t = line.toCharArray();for (char a : t) {// 判断是否为汉字字符if (Character.toString(a).matches("[\\u4E00-\\u9FA5]+")) {// System.out.print("字符串含有汉字");// System.out.print(line.replaceAll("[^\\u4e00-\\u9fa5]", ""));//获取中文名称String tableChineseName =line.replaceAll("[^\\u4e00-\\u9fa5]", "");return tableChineseName;}}}return null;}
}