All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gitee.summer9102.develop.common.util.MapperGenerateUtil Maven / Gradle / Ivy

package com.gitee.summer9102.develop.common.util;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MapperGenerateUtil {

    /**
     * 换行符
     */
    private static String newLine = "\n";

    /**
     * 数据库表映射工具
     *
     * @param dataSource
     * @param oneTableName 表名
     * @param basePath     System.getProperty("user.dir");
     * @param modelPackage 实体类包路径
     * @param daoPackage   dao接口包路径
     */
    public static void codegenForOneTable(DataSource dataSource, String oneTableName, String basePath, String modelPackage, String daoPackage) {
        if (!basePath.endsWith(File.separator)) {
            basePath = basePath + File.separator;
        }
        String sourcePath = basePath + "src/main/java/";
        String sqlMapperPath = basePath + "src/main/resources/mapper/";
        String fileCharset = "utf-8";

        String modelFilePath = sourcePath + modelPackage.replace(".", File.separator) + File.separator + getModelNameByTableName(oneTableName) + ".java";
        String daoFilePath = sourcePath + daoPackage.replace(".", File.separator) + File.separator + getDaoNameByTableName(oneTableName) + ".java";
        String sqlMapperFilePath = sqlMapperPath + getSqlMapperFileNameByTableName(oneTableName);

        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            TableInfo tableInfo = getTableInfo(conn, oneTableName);
            if (tableInfo.getPrimaryKeys().size() == 0) {
                System.err.println("[ERROR] " + oneTableName + " 没有主键,无法生成。");
                return;
            }
            {
                File modelFile = new File(modelFilePath);
                if (modelFile.exists()) {
                    System.err.println("[WARN] 实体类 " + getModelNameByTableName(oneTableName) + " 已存在,将会覆盖。");
                }
                String modelSource = buildModel(tableInfo, modelPackage);
                writeText(modelFile, modelSource, fileCharset);
            }
            {
                File sqlMapperFile = new File(sqlMapperFilePath);
                if (!sqlMapperFile.exists()) {
                    // 自定义SQL文件不存在,才创建
                    String sqlMapperSource = buildSqlMapper(tableInfo, daoPackage);
                    writeText(sqlMapperFile, sqlMapperSource, fileCharset);
                }
            }
            {
                File daoFile = new File(daoFilePath);
                if (!daoFile.exists()) {
                    // 不存在才创建
                    String daoSource = buildDaoInterface(tableInfo, daoPackage, modelPackage);
                    writeText(daoFile, daoSource, fileCharset);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static String getAuthorInfo() {
        return "/**" + newLine +
                " * Created on " + LocalDateTime.now().format(DateFormatUtil.getDateTimeFormatter()) + newLine +
                " */" + newLine;
    }

    private static String buildModel(TableInfo tableInfo, String modalPackage) {
        StringBuilder buf = new StringBuilder(2048);
        String modalName = getModelNameByTableName(tableInfo.getTableName());
        buf.append("package ").append(modalPackage).append(";").append(newLine);
        buf.append(newLine);
        buf.append("import lombok.Getter;").append(newLine);
        buf.append("import lombok.Setter;").append(newLine);
        buf.append("import tk.mybatis.mapper.annotation.KeySql;").append(newLine);
        buf.append(newLine);
        buf.append("import javax.persistence.Id;").append(newLine);
        if (tableInfo.isImportTime()) {
            buf.append("import java.time.*;").append(newLine);
        }
        if (tableInfo.isImportMath()) {
            buf.append("import java.math.*;").append(newLine);
        }
        buf.append(newLine);
        buf.append(getAuthorInfo());
        buf.append("@Getter").append(newLine);
        buf.append("@Setter").append(newLine);
        buf.append("public class ").append(modalName).append(" implements java.io.Serializable {").append(newLine);
        buf.append(newLine);

        Map columnCommentMap = tableInfo.getColumnCommentMap();

        //主键字段
        for (String primaryKey : tableInfo.getPrimaryKeys()) {
            String propertyName = underlineToCamel(primaryKey);
            String javaType = getJavaTypeByJdbcType(tableInfo.getColumnTypes().get(primaryKey));

            String comment = columnCommentMap.get(primaryKey);
            if (comment != null) {
                buf.append("    /**").append(newLine);
                buf.append("     * ").append(comment).append(newLine);
                buf.append("     */").append(newLine);
            }
            buf.append("    ").append("@Id").append(newLine);
            if (tableInfo.isPrimaryKeyAutoIncrement()) {
                buf.append("    ").append("@KeySql(useGeneratedKeys = true)").append(newLine);
            }
            buf.append("    ").append("private ").append(javaType).append(" ").append(propertyName).append(";").append(newLine);
        }
        //其他字段
        for (String column : tableInfo.getColumns()) {
            if (tableInfo.getPrimaryKeys().contains(column)) {
                continue;
            }
            String propertyName = underlineToCamel(column);
            String javaType = getJavaTypeByJdbcType(tableInfo.getColumnTypes().get(column));

            String comment = columnCommentMap.get(column);
            if (comment != null) {
                buf.append("    /**").append(newLine);
                buf.append("     * ").append(comment).append(newLine);
                buf.append("     */");
            }
            buf.append(newLine);
            buf.append("    ").append("private ").append(javaType).append(" ").append(propertyName).append(";").append(newLine);
        }
        buf.append(newLine);
        buf.append("}");
        return buf.toString();
    }

    private static String buildDaoInterface(TableInfo tableInfo, String daoPackage, String modalPackage) {
        StringBuilder buf = new StringBuilder(256);
        String tableName = tableInfo.getTableName();
        String daoName = getDaoNameByTableName(tableName);
        String modalName = getModelNameByTableName(tableInfo.getTableName());
        String modalNameWithPackage = modalPackage + "." + modalName;
        buf.append("package ").append(daoPackage).append(";").append(newLine);
        buf.append(newLine);
        buf.append("import ").append("com.gitee.summer9102.develop.mysql.config.CommonMapper;").append(newLine);
        buf.append("import ").append(modalNameWithPackage).append(";").append(newLine);
        buf.append(newLine);
        buf.append("public interface ").append(daoName).append(" extends CommonMapper<").append(modalName).append(">").append(" {").append(newLine);
        buf.append(newLine);
        buf.append("}");
        return buf.toString();
    }

    private static String buildSqlMapper(TableInfo tableInfo, String daoPackage) {
        StringBuilder buf = new StringBuilder(1024);
        String daoName = daoPackage + "." + getDaoNameByTableName(tableInfo.getTableName());
        buf.append("").append(newLine);
        buf.append("").append(newLine);
        buf.append("").append(newLine).append(newLine);
        buf.append("");
        return buf.toString();
    }

    private static String getJavaTypeByJdbcType(String jdbcType) {
        if (jdbcType.equalsIgnoreCase("int") || jdbcType.equalsIgnoreCase("tinyint")
                || jdbcType.equalsIgnoreCase("smallint") || jdbcType.equalsIgnoreCase("mediumint")) {
            return "Integer";
        } else if (jdbcType.equalsIgnoreCase("bigint")) {
            return "Long";
        } else if (jdbcType.equalsIgnoreCase("varchar") || jdbcType.equalsIgnoreCase("char")
                || jdbcType.equalsIgnoreCase("text") || jdbcType.equalsIgnoreCase("longtext")) {
            return "String";
        } else if (jdbcType.equalsIgnoreCase("double")) {
            return "Double";
        } else if (jdbcType.equalsIgnoreCase("float")) {
            return "Float";
        } else if (jdbcType.equalsIgnoreCase("decimal")) {
            return "BigDecimal";
        } else if (jdbcType.equalsIgnoreCase("datetime") || jdbcType.equalsIgnoreCase("timestamp")) {
            return "LocalDateTime";
        } else if (jdbcType.equalsIgnoreCase("date")) {
            return "LocalDate";
        } else if (jdbcType.equalsIgnoreCase("time")) {
            return "LocalTime";
        }
        throw new RuntimeException("not supported JDBC Type : \"" + jdbcType + "\"!");
    }

    private static TableInfo getTableInfo(Connection conn, String tableName)
            throws Exception {
        //查要生成实体类的表
        String schema = conn.getCatalog();
        String sql = "SELECT * FROM " + schema + "." + tableName;
        PreparedStatement pStemt;
        TableInfo tableInfo;
        try {
            pStemt = conn.prepareStatement(sql);
            ResultSetMetaData rsmd = pStemt.getMetaData();
            int size = rsmd.getColumnCount();//统计列
            List columns = new ArrayList<>(size);
            Map columnTypes = new HashMap<>(size);
            Map columnCommentMap = new HashMap<>(size);
            // 是否需要导入包java.math.*
            boolean importMath = false;
            // 是否需要导入包java.time.*
            boolean importTime = false;
            {
                String commentSql =
                        "SELECT column_name,column_comment FROM information_schema.COLUMNS WHERE table_name='"
                                + tableName + "' and table_schema = '" + schema + "'";
                PreparedStatement pStemt2 = conn.prepareStatement(commentSql);
                ResultSet rs = pStemt2.executeQuery();
                while (rs.next()) {
                    String column_name = rs.getString("column_name").toLowerCase();
                    String column_comment = rs.getString("column_comment");
                    if (column_comment != null && column_comment.length() > 0) {
                        columnCommentMap.put(column_name, column_comment);
                    }
                }
            }

            for (int i = 0; i < size; i++) {
                String columnName = rsmd.getColumnName(i + 1).toLowerCase();
                columns.add(columnName);
                String colType = rsmd.getColumnTypeName(i + 1);
                colType = colType.replace("UNSIGNED", "").replace("unsigned", "").trim().toUpperCase();
                columnTypes.put(columnName, colType);
                if (colType.equalsIgnoreCase("datetime") || colType.equalsIgnoreCase("timestamp")
                        || colType.equalsIgnoreCase("date") || colType.equalsIgnoreCase("time")) {
                    importTime = true;
                } else if (colType.equalsIgnoreCase("decimal")) {
                    importMath = true;
                }
            }
            List primaryKeys = new ArrayList<>(2);
            {
                String selectPrimaryKeysSql =
                        "SELECT column_name FROM information_schema.KEY_COLUMN_USAGE WHERE constraint_name='PRIMARY' AND table_name='"
                                + tableName + "' and table_schema = '" + schema + "'";
                PreparedStatement pStemt2 = conn.prepareStatement(selectPrimaryKeysSql);
                ResultSet rs = pStemt2.executeQuery();
                while (rs.next()) {
                    String primaryKey = rs.getString("column_name");
                    primaryKeys.add(primaryKey);
                }
            }

            // 否则主键一定不是自增长
            boolean primaryKeyAutoIncrement = false;
            if (primaryKeys.size() == 1) {
                // 有主键,且主键只有一个,才判断主键是否是自增长
                String selectPrimaryKeyAutoIncrementSql =
                        "SELECT auto_increment FROM information_schema.TABLES WHERE table_name='"
                                + tableName + "' and table_schema = '" + schema + "'";
                PreparedStatement pStemt3 = conn.prepareStatement(selectPrimaryKeyAutoIncrementSql);
                ResultSet rs = pStemt3.executeQuery();
                if (rs.next()) {
                    Object autoIncrementObj = rs.getObject("auto_increment");
                    if (autoIncrementObj != null) {
                        // 自增长主键
                        primaryKeyAutoIncrement = true;
                    }
                }
            }

            tableInfo = new TableInfo();
            tableInfo.setTableName(tableName);
            tableInfo.setColumns(columns);
            tableInfo.setColumnTypes(columnTypes);
            tableInfo.setImportTime(importTime);
            tableInfo.setImportMath(importMath);
            tableInfo.setPrimaryKeyAutoIncrement(primaryKeyAutoIncrement);
            tableInfo.setPrimaryKeys(primaryKeys);
            tableInfo.setColumnCommentMap(columnCommentMap);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return tableInfo;
    }

    private static String getSqlMapperFileNameByTableName(String tableName) {
        return tableName + "-mapper.xml";
    }

    private static String getModelNameByTableName(String tableName) {
        return initCapAndUnderlineToCamel(tableName);
    }

    private static String getDaoNameByTableName(String tableName) {
        return getModelNameByTableName(tableName) + "Mapper";
    }

    private static void writeText(File targetFile, String content, String charSet) {
        OutputStreamWriter out = null;
        if (!targetFile.getParentFile().exists()) {
            targetFile.getParentFile().mkdirs();
        }
        try {
            out = new OutputStreamWriter(new FileOutputStream(targetFile), charSet);
            out.write(content.toCharArray());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static String initCap(String src) {
        if (src == null) {
            return null;
        }
        if (src.length() > 1) {
            return src.substring(0, 1).toUpperCase() + src.substring(1);
        } else {
            return src.toUpperCase();
        }
    }

    private static String downCap(String src) {
        if (src.length() > 1) {
            return src.substring(0, 1).toLowerCase() + src.substring(1);
        } else {
            return src.toLowerCase();
        }
    }

    /**
     * 驼峰处理shop_name -> shopName
     */
    private static String underlineToCamel(String param) {
        if (param == null || param.equals("")) {
            return "";
        }
        Pattern p = Pattern.compile("_");
        StringBuilder builder = new StringBuilder(param);
        Matcher mc = p.matcher(param);
        int i = 0;
        char found;
        while (mc.find()) {
            builder.deleteCharAt(mc.start() - i);
            found = builder.charAt(mc.start() - i);
            builder.replace(mc.start() - i, mc.start() - i + 1, Character.toString(found).toUpperCase());
            i++;
        }
        return builder.toString();
    }

    /**
     * 驼峰处理ly_share_user -> LyShareUser
     */
    private static String initCapAndUnderlineToCamel(String param) {
        String rs = underlineToCamel(param);
        return initCap(rs);
    }

    private static class TableInfo {

        private String tableName;
        private List primaryKeys;
        private boolean primaryKeyAutoIncrement;
        private List columns;
        private Map columnTypes;
        private Map columnCommentMap;
        // 是否需要导入包java.math.*
        private boolean importMath;
        // 是否需要导入包java.time.*
        private boolean importTime;

        String getTableName() {
            return tableName;
        }

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

        List getPrimaryKeys() {
            return primaryKeys;
        }

        void setPrimaryKeys(List primaryKeys) {
            this.primaryKeys = primaryKeys;
        }

        boolean isPrimaryKeyAutoIncrement() {
            return primaryKeyAutoIncrement;
        }

        void setPrimaryKeyAutoIncrement(boolean primaryKeyAutoIncrement) {
            this.primaryKeyAutoIncrement = primaryKeyAutoIncrement;
        }

        List getColumns() {
            return columns;
        }

        void setColumns(List columns) {
            this.columns = columns;
        }

        Map getColumnTypes() {
            return columnTypes;
        }

        void setColumnTypes(Map columnTypes) {
            this.columnTypes = columnTypes;
        }

        Map getColumnCommentMap() {
            return columnCommentMap;
        }

        void setColumnCommentMap(Map columnCommentMap) {
            this.columnCommentMap = columnCommentMap;
        }

        boolean isImportMath() {
            return importMath;
        }

        void setImportMath(boolean importMath) {
            this.importMath = importMath;
        }

        boolean isImportTime() {
            return importTime;
        }

        void setImportTime(boolean importTime) {
            this.importTime = importTime;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy