根据实体类生成表生成语句

新接手一个项目,没有数据库文件,并且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;

/**
 * 根据实体类生成表生成语句
 */
@Slf4j
 class 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());
            //处理className
            className = 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();
    }
    /**
     * 获取表中文名称
     */
    @SneakyThrows
    private 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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值