自動生成小工具(一):根據建表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;
    }
}

 

 

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