自动生成小工具(一):根据建表sql自动生成对应的model.java文件

Talk is cheap,show me the code.

 

/**
 * 功能:根据提供的数据库表结构文件(.sql文件),自动生成对应的model类。
 *
 * 根据数据库表的建表语句,生成对应的实体类。
 * JDK版本1.8
 * 数据库使用的是mysql
 *
 * 注意事项:
 * 1,必须要有COMMENT,并且COMMENT用英文单引号包围起来。
 * 2,请注意sql文件格式。我这里会提供一个模板供大家参考。
 * 3,请确保在D盘下的目录是对的。可以根据自己的情况,修改代码中硬编码的路径。
 *
 */

 

自己写的,可以直接跑。如有问题,请联系,谢谢。

 

一,程序入口核心类:GenEntityMappingForDatabase.java


 
import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 功能:根据提供的数据库表结构文件(.sql文件),自动生成对应的model类。
 *
 * 根据数据库表的建表语句,生成对应的实体类。
 * JDK版本1.8
 * 数据库使用的是mysql
 *
 * 注意事项:
 * 1,必须要有COMMENT,并且COMMENT用英文单引号包围起来。
 * 2,请注意sql文件格式。我这里会提供一个模板供大家参考。
 * 3,请确保在D盘下的目录是对的。可以根据自己的情况,修改代码中硬编码的路径。
 *
 */
public class GenEntityMappingForDatabase {

    /**
     * 源文件路径
     */
    private static final String SOURCE_FILE_PATH = "D:\\sourcefile\\";

    /**
     * 源文件名称
     */
    private static final String SOURCE_FILE_NAME = "table_create";

    /**
     * 源文件后缀
     */
    private static final String SOURCE_FILE_SUFFIX = "sql";

    /**
     * 目标文件路径
     */
    private static final String TARGET_FILE_PATH = "D:\\targetfile\\";

    /**
     * 目标文件名称
     */
    private static final String TARGET_FILE_NAME = "TableMappedModel";

    /**
     * 目标文件后缀
     */
    private static final String TARGET_FILE_SUFFIX = "java";

    /**
     *  换行符
     */
    private static final String LINE_BREAK = "\r\n";

    /**
     * Mysql建表语句关键字
     */
    private final static Map<String, String> MYSQL_KEY_WORD_MAP = new HashMap();
    static {
        MYSQL_KEY_WORD_MAP.put("ENGINE", "ENGINE");
        MYSQL_KEY_WORD_MAP.put("CHARACTER", "CHARACTER");
        MYSQL_KEY_WORD_MAP.put("COLLATE", "COLLATE");
    }


    public static void main(String[] args) {

        File fileObj = new File(SOURCE_FILE_PATH + SOURCE_FILE_NAME + "." + SOURCE_FILE_SUFFIX);

        GenEntityMappingForDatabase genEntityMappingForDatabase = new GenEntityMappingForDatabase();
        TableInfo tableInfo = genEntityMappingForDatabase.getFieldInfo(fileObj);
        genEntityMappingForDatabase.genJavaFileBaseMysql(tableInfo);
    }

    /**
     * 解析sql建表语句文件,得到FieldInfo集合
     * @param fileObj
     * @return
     */
    public TableInfo getFieldInfo(File fileObj) {
        BufferedReader reader = null;
        InputStream in = null;

        TableInfo tableInfo = new TableInfo();
        List<FieldInfo> list = new ArrayList<>();
        List<FieldInfo> listParsed = null;

        try {
            reader = new BufferedReader(new FileReader(fileObj));
            in = new FileInputStream(fileObj);
            String line = null;
            int count = 0;
            while((line  = reader.readLine()) != null) {

                // 第一行
                if (line.toUpperCase().contains("CREATE TABLE")) {

                    tableInfo.setTableName(parseTableName(line));
                    continue;
                }

                // PRIMARY KEY 行
                if (line.toUpperCase().contains("PRIMARY KEY")) {
                    tableInfo.setPrimaryKeyDB(line.substring(line.indexOf("(") + 1, line.indexOf(")")));
                    continue;
                }

                // 建表语句结束的右括号 行
                if (line.trim().startsWith(")")) {
                    continue;
                }

                // 表备注信息
                if (line.trim().toUpperCase().startsWith("COMMENT")) {
                    continue;
                }

                boolean keyWordFlag = false;
                for (Map.Entry<String, String> entry : MYSQL_KEY_WORD_MAP.entrySet()) {
                    if (line.toUpperCase().contains(entry.getKey())) {
                        keyWordFlag = true;
                        break;
                    }
                }

                if (keyWordFlag){
                    continue;
                }

                // 递归处理,拿到字段名/字段类型/字段备注信息,然后存入ArrayList
                parseFiledInfo(line, list);


            }

            listParsed = convertMysql2Java(list, tableInfo);

            tableInfo.setFieldList(listParsed);

        } catch (IOException e) {
            System.out.println(" catch 分支 IOException " + e);
        } finally {
            try {
                in.close();
            } catch (IOException e){
                System.out.println(" finally 分支 IOException " + e);
            }

        }

        return tableInfo;
    }

    public void genJavaFileBaseMysql(TableInfo tableInfo) {
        genTargetFile(tableInfo);
    }

    private String parseTableName(String line) {
        return line.replaceFirst("CREATE", "").replaceFirst("TABLE", "").replaceFirst("\\(", "").trim().toLowerCase();
    }


    private List<FieldInfo> parseFiledInfo(String line, List<FieldInfo> list) {

        // 去掉每行前面的空格
        String lineWithoutFrontBlank = parLineFrontBlank(line);
        // 字段名
        String fieldNameDB = lineWithoutFrontBlank.substring(0, lineWithoutFrontBlank.indexOf(" "));
        // 字段备注信息
        String comment = lineWithoutFrontBlank.substring(lineWithoutFrontBlank.indexOf("'") + 1, lineWithoutFrontBlank.lastIndexOf("'"));
        String lineNotStartsWithBlankAndFieldName = parLineFrontBlank(lineWithoutFrontBlank.substring(lineWithoutFrontBlank.indexOf(" ")));
        // 字段数据类型
        String dataTypeMysql = lineNotStartsWithBlankAndFieldName.substring(0, lineNotStartsWithBlankAndFieldName.indexOf(" "));

        // 去掉数据类型后面的括号内容
        if (dataTypeMysql.trim().endsWith(")")) {
            dataTypeMysql = dataTypeMysql.substring(0, dataTypeMysql.indexOf("("));
        }

        FieldInfo fieldInfo = new FieldInfo(fieldNameDB, null, dataTypeMysql, null, comment);
        list.add(fieldInfo);
        return list;
    }

    /**
     * 递归去掉每行前面的空格
     * @param tempStr
     * @return
     */
    private String parLineFrontBlank(String tempStr) {

        if (tempStr.startsWith(" ")) {
            String newTempStr = tempStr.substring(1);
            return parLineFrontBlank(newTempStr);
        }

        return tempStr;
    }

    private void genTargetFile(TableInfo tableInfo) {

        List<FieldInfo> listParsed = tableInfo.getFieldList();
        FileOutputStream fos = null;

        try {

            File f1 = new File(TARGET_FILE_PATH + TARGET_FILE_NAME + "." + TARGET_FILE_SUFFIX);
            if (!f1.exists()){
                f1.getParentFile().mkdirs();
            }

            fos = new FileOutputStream(f1);

            // 生成文件头

            fos.write(("/**" + LINE_BREAK).getBytes());
            fos.write((" @author Changqing Yang" + LINE_BREAK).getBytes());
            fos.write((" * @date 2019/10/30" + LINE_BREAK).getBytes());
            fos.write((" */" + LINE_BREAK).getBytes());
            fos.write(("public class " + TARGET_FILE_NAME + " {" + LINE_BREAK).getBytes());
            fos.write(LINE_BREAK.getBytes());

            // 循环写入字段
            for (FieldInfo fieldInfo : listParsed) {

                String filedNameJava = fieldInfo.getFieldNameJava();
                String dataTypeJava = fieldInfo.getDataTypeJava();
                String comment = fieldInfo.getComment();

                fos.write(("    // " + comment + LINE_BREAK).getBytes());
                fos.write(("    private " + dataTypeJava + " " + filedNameJava + ";" + LINE_BREAK).getBytes());

            }

            // 生成getter/setter方法
            genGetterAndSetter(fos, listParsed);

            // 生成文件尾部
            fos.write(("}" + LINE_BREAK).getBytes());

        } catch (IOException e) {
            System.out.println("catch " + e);
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                System.out.println("finally " + e);
            }
        }
    }

    private List<FieldInfo> convertMysql2Java(List<FieldInfo> list, TableInfo tableInfo) {

        List<FieldInfo> listParsed = new ArrayList<>();

        for (FieldInfo fieldInfo : list) {

            // 如果该字段是主键
            if (StringUtils.equals(fieldInfo.getFieldNameJava(), tableInfo.getPrimaryKeyJava())) {
                tableInfo.setPrimaryKeyJava(mappingMysqlFieldName2Java(tableInfo.getPrimaryKeyDB()));
                tableInfo.setPrimaryKeyDataType(fieldInfo.getDataTypeMysql());
            }
            // mysql字段转java字段
            fieldInfo.setFieldNameJava(mappingMysqlFieldName2Java(fieldInfo.getFieldNameDB()));
            // mysql字段类型 转 java 数据类型
            fieldInfo.setDataTypeJava(mappingMysqlDataType2Java(fieldInfo.getDataTypeMysql()));

            listParsed.add(fieldInfo);
        }

        return listParsed;
    }

    private String mappingMysqlDataType2Java(String dataTypeMysql) {
//
//        // 去掉数据类型后面的括号内容
//        if (dataTypeMysql.trim().endsWith(")")) {
//            dataTypeMysql = dataTypeMysql.substring(0, dataTypeMysql.indexOf("("));
//        }

        // 字符串
        if (MysqlDataTypeConstants.MYSQL_DATA_TYPE_VARCHAR.containsValue(dataTypeMysql.toLowerCase())) {
            return "String";
        }

        // 整形
        if (MysqlDataTypeConstants.MYSQL_DATA_TYPE_INT.containsValue(dataTypeMysql.toLowerCase())) {
            return "Integer";
        }

        // 长整形
        if (MysqlDataTypeConstants.MYSQL_DATA_TYPE_LONG.containsValue(dataTypeMysql.toLowerCase())) {
            return "Long";
        }

        // date
        if (MysqlDataTypeConstants.MYSQL_DATA_TYPE_DATE.containsValue(dataTypeMysql.toLowerCase())) {
            return "Date";
        }

        return dataTypeMysql;
    }

    /**
     * Mysql字段名称转java字段名称
     * @param filedName
     * @return
     */
    private String mappingMysqlFieldName2Java(String filedName) {

        // 去掉数据类型后面的括号内容
        if (!filedName.contains("_")) {
            return filedName;
        }

        return parseUnderLine(filedName);
    }

    /**
     * 递归处理Mysql字段名称中的下划线
     */
    private String parseUnderLine(String filedName) {

        int underLineIndex = filedName.indexOf("_");
        String parsedFieldName = filedName.replaceFirst(filedName.substring(underLineIndex, underLineIndex + 2), filedName.substring(underLineIndex + 1, underLineIndex + 2).toUpperCase());

        if (!parsedFieldName.contains("_")) {
            return parsedFieldName;
        }

        return parseUnderLine(parsedFieldName);
    }

    /**
     * 根据字段名,生成getter/setter
     */
    private void genGetterAndSetter(FileOutputStream fos, List<FieldInfo> list) {

        String fieldNameJava = null;
        String fieldNameUpperCase = null;
        String dataTypeJava = null;
        for (FieldInfo fieldInfo : list) {
            fieldNameJava = fieldInfo.getFieldNameJava();
            dataTypeJava = fieldInfo.getDataTypeJava();

            // 字段名首字母转大写
            fieldNameUpperCase = fieldNameJava.substring(0, 1).toUpperCase().concat(fieldNameJava.substring(1));
            try {
                fos.write(LINE_BREAK.getBytes());
                fos.write(("    public " + dataTypeJava + " get" + fieldNameUpperCase + "() {" + LINE_BREAK).getBytes());
                fos.write(("        return " + fieldNameJava + ";" + LINE_BREAK).getBytes());
                fos.write(("    }" + LINE_BREAK).getBytes());
                fos.write(LINE_BREAK.getBytes());
                fos.write(("    public void set" + fieldNameUpperCase + "(" + dataTypeJava + " " + fieldNameJava + ") {" + LINE_BREAK).getBytes());
                fos.write(("        this." + fieldNameJava + " = " + fieldNameJava + ";" + LINE_BREAK).getBytes());
                fos.write(("    }" + LINE_BREAK).getBytes());
            } catch (IOException e) {
                System.out.println("genGetterAndSetter catch " + e);
            }
        }


    }


}

 

 

二,建表语句中所有表字段封装实体类:FieldInfo.java


 
/**
 * 建表语句中所有表字段封装实体类
 */
public class FieldInfo {

    /**
     * 字段名(数据库字段格式)
     */
    private String fieldNameDB;

    /**
     * 字段名(java驼峰格式)
     */
    private String fieldNameJava;

    /**
     * mysql数据类型
     */
    private String dataTypeMysql;

    /**
     * java数据类型
     */
    private String dataTypeJava;

    /**
     * 字段conmment备注信息
     */
    private String comment;

    public FieldInfo(String fieldNameDB, String fieldNameJava, String dataTypeMysql, String dataTypeJava, String comment) {
        this.fieldNameDB = fieldNameDB;
        this.fieldNameJava = fieldNameJava;
        this.dataTypeMysql = dataTypeMysql;
        this.dataTypeJava = dataTypeJava;
        this.comment = comment;
    }

    public String getFieldNameDB() {
        return fieldNameDB;
    }

    public void setFieldNameDB(String fieldNameDB) {
        this.fieldNameDB = fieldNameDB;
    }

    public String getFieldNameJava() {
        return fieldNameJava;
    }

    public void setFieldNameJava(String fieldNameJava) {
        this.fieldNameJava = fieldNameJava;
    }

    public String getDataTypeMysql() {
        return dataTypeMysql;
    }

    public void setDataTypeMysql(String dataTypeMysql) {
        this.dataTypeMysql = dataTypeMysql;
    }

    public String getDataTypeJava() {
        return dataTypeJava;
    }

    public void setDataTypeJava(String dataTypeJava) {
        this.dataTypeJava = dataTypeJava;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }
}

 

三,建表语句对应实体类:TableInfo.java


 
import java.util.List;

/**
 * 建表语句对应实体类
 */
public class TableInfo {

    /**
     * 表名
     */
    private String tableName;

    /**
     * 主键(数据库字段名格式)
     */
    private String primaryKeyDB;

    /**
     * 主键(java驼峰命名格式)
     */
    private String primaryKeyJava;

    /**
     * 主键的数据类型
     */
    private String primaryKeyDataType;

    /**
     * 表字段集合
     */
    private List<FieldInfo> fieldList;

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String getPrimaryKeyDB() {
        return primaryKeyDB;
    }

    public void setPrimaryKeyDB(String primaryKeyDB) {
        this.primaryKeyDB = primaryKeyDB;
    }

    public String getPrimaryKeyJava() {
        return primaryKeyJava;
    }

    public void setPrimaryKeyJava(String primaryKeyJava) {
        this.primaryKeyJava = primaryKeyJava;
    }

    public String getPrimaryKeyDataType() {
        return primaryKeyDataType;
    }

    public void setPrimaryKeyDataType(String primaryKeyDataType) {
        this.primaryKeyDataType = primaryKeyDataType;
    }

    public List<FieldInfo> getFieldList() {
        return fieldList;
    }

    public void setFieldList(List<FieldInfo> fieldList) {
        this.fieldList = fieldList;
    }
}

 

四,常量定义类:MysqlDataTypeConstants.java

 

import java.util.HashMap;
import java.util.Map;

/**
 * 常量定义类
 */
public class MysqlDataTypeConstants {

    /**
     * Mysql数据类型之字符串(整理的可能不够完整,欢迎大家补充。)
     */
    public final static Map<String, String> MYSQL_DATA_TYPE_VARCHAR = new HashMap();
    static {
        MYSQL_DATA_TYPE_VARCHAR.put("varchar", "varchar");
        MYSQL_DATA_TYPE_VARCHAR.put("json", "json");
        MYSQL_DATA_TYPE_VARCHAR.put("char", "char");
    }

    /**
     * Mysql数据类型之整形(整理的可能不够完整,欢迎大家补充。)
     */
    public final static Map<String, String> MYSQL_DATA_TYPE_INT = new HashMap();
    static {
        MYSQL_DATA_TYPE_INT.put("int", "int");
        MYSQL_DATA_TYPE_INT.put("bit", "bit");
    }

    /**
     * Mysql数据类型之长整形(整理的可能不够完整,欢迎大家补充。)
     */
    public final static Map<String, String> MYSQL_DATA_TYPE_LONG = new HashMap();
    static {
        MYSQL_DATA_TYPE_LONG.put("bigint", "bigint");
        MYSQL_DATA_TYPE_LONG.put("long", "long");
    }

    /**
     * Mysql数据类型之整形(整理的可能不够完整,欢迎大家补充。)
     */
    public final static Map<String, String> MYSQL_DATA_TYPE_DATE = new HashMap();
    static {
        MYSQL_DATA_TYPE_DATE.put("datetime", "datetime");
        MYSQL_DATA_TYPE_DATE.put("timestamp", "timestamp");
    }

}

 

五,sql文件模板:table_create.sql

 

注意,这个文件的路径是:D:\sourcefile,如果需要修改,请把源码中的对应路径也修改掉。

 

CREATE TABLE product_info (   
   product_id  bigint COMMENT '产品编号' NOT NULL,
   product_name varchar(128) COMMENT '产品名称' NOT NULL,
   status varchar(20) COMMENT '产品状态 0-未上架 1-已上架 2-已下架 3-已删除',
   create_time timestamp COMMENT '创建时间' NOT NULL,
   update_time timestamp COMMENT '最后更新时间' NOT NULL,   
   PRIMARY KEY(activity_id) USING BTREE
)
COMMENT = '产品信息' 
ENGINE = InnoDB
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;

 

六,运行生成的model文件示例TableMappedModel.java

 

默认生成文件的路径是:D:\targetfile,如果需要修改,请把源码中的对应路径也修改掉。

 

/**
 @author Changqing Yang
 * @date 2019/10/30
 */
public class TableMappedModel {

    // 产品编号
    private Long productId;
    // 产品名称
    private String productName;
    // 产品状态 0-未上架 1-已上架 2-已下架 3-已删除
    private String status;
    // 创建时间
    private Date createTime;
    // 最后更新时间
    private Date updateTime;

    public Long getProductId() {
        return productId;
    }

    public void setProductId(Long productId) {
        this.productId = productId;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章