6

逆向 MySQL 生成实体类

 3 years ago
source link: https://my.oschina.net/kezhen/blog/4871232
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
逆向 MySQL 生成实体类

支持多个表(或者根据直接查询数据表的所有表)

前沿,在程序猿确定需求文档时候,设计好了数据表后,然后第一步就是及时提交实体类了,好方便小组同事写拓展业务代码。

之前每次接到需求,都是设计一两张表,我就赖得写一键生成实体类代码,蠢办法一个Ctrl+C,Ctrl+V,请叫我复制粘贴工程师。

                                                               src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20181026%2F07a2bd062582412fbd0690505fa612d3.gif&refer=http%3A%2F%2F5b0988e595225.cdn.sohucs.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1611987541&t=80365ac052cf297f62105ed4733d4e90

但是这周接到的需求,重构XXX系统,和老大,同事们开完会,讨论后,建立了个8张表。。。。难道今天要报废我的Ctrl,C,V 键帽,还有我的快手。

src=http%3A%2F%2Fwww.weixinbqb.com%2Fuploads%2Fallimg%2F200102%2F1_0102104509E04.jpg&refer=http%3A%2F%2Fwww.weixinbqb.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1611987980&t=cdca137af01514d11dd589d7b310f82e

作为程序猿,不折腾一番咋行呢,必须写个手动一键生成啊

全局代码如下:

package net.oschina.tester;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;

public class GenEntityMysql {

    private String outPath = "D:\\data\\";
    private String packageOutPath = "net.oschina.beans";//指定实体生成所在包的路径
    private String authorName = "author_name";//作者名字
    private String[] colnames; // 列名数组
    private String[] colTypes; //列名类型数组
    private int[] colSizes; //列名大小数组
    private Map<String, Integer> colMap = new HashMap<>();//列名-列名大小
    private Map comment;     //字段注释
    private boolean f_util = false; // 是否需要导入包java.util.*
    private boolean f_sql = false; // 是否需要导入包java.sql.*
    private boolean cap = false;//是否首字母大写
    private boolean hump = false;//是否驼峰

    //数据库连接
    private static final String URL = "jdbc:mysql://192.168.1.50:3306/oscdb";
    private static final String NAME = "root";
    private static final String PASS = "oschina";
    private static final String DRIVER = "com.mysql.jdbc.Driver";

    /*
     * 构造函数
     */
    public GenEntityMysql(String tablename) {
        //创建连接
        Connection con = null;
        //查要生成实体类的表
        String sql = "select * from " + tablename;
        PreparedStatement pStemt = null;
        PreparedStatement pStemt2 = null;
        try {
            try {
                Class.forName(DRIVER);
            } catch (ClassNotFoundException e1) {
                e1.printStackTrace();
            }
            con = DriverManager.getConnection(URL, NAME, PASS);
            pStemt = con.prepareStatement(sql);
            ResultSetMetaData rsmd = pStemt.getMetaData();
            int size = rsmd.getColumnCount();    //统计列
            colnames = new String[size];
            colTypes = new String[size];
            colSizes = new int[size];
            for (int i = 0; i < size; i++) {
                String colName = rsmd.getColumnName(i + 1);
                int colSize = rsmd.getColumnDisplaySize(i + 1);
                colnames[i] = colName;
                colTypes[i] = rsmd.getColumnTypeName(i + 1);

                if (colTypes[i].equalsIgnoreCase("datetime")) {
                    f_util = true;
                }
                if (colTypes[i].equalsIgnoreCase("image") || colTypes[i].equalsIgnoreCase("text")) {
                    f_sql = true;
                }
                colSizes[i] = colSize;
                colMap.put(colName, colSize);
            }

            //获取数据库字段注释
            String commentSql = " show full fields from " + tablename;
            comment = new HashMap();
            pStemt2 = con.prepareStatement(commentSql);
            ResultSet rs2 = pStemt2.executeQuery();
            while (rs2.next()) {
                String comm = rs2.getString("Comment");
                if (null != comm && !comm.equals("")) {
                    comment.put(rs2.getString("Field"), comm);
                } else {
                    comment.put(rs2.getString("Field"), rs2.getString("Field"));
                }
            }
            System.out.println(comment);
            String content = parse(tablename, colnames, colTypes, colSizes);

            try {
                File file = new File(outPath);
                file.mkdirs();
                FileWriter fw = new FileWriter(outPath + initcap(colnameToHump(tablename)) + ".java");
                PrintWriter pw = new PrintWriter(fw);
                pw.println(content);
                pw.flush();
                pw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 功能:生成实体类主体代码
     *
     * @param colnames
     * @param colTypes
     * @param colSizes
     * @return
     */
    private String parse(String tablename, String[] colnames, String[] colTypes, int[] colSizes) {
        StringBuffer sb = new StringBuffer();
        sb.append("package " + this.packageOutPath + ";\r\n");
        sb.append("\r\n");
        //判断是否导入工具包
        if (f_util) {
            sb.append("import java.util.Date;\r\n");
        }
        if (f_sql) {
            sb.append("import java.sql.*;\r\n");
        }
        //注释部分
        sb.append("\r\n");
        sb.append("/**\r\n");
        sb.append(" * " + tablename + " 实体类\r\n");
        //sb.append(" * " + new Date() + " " + this.authorName + "\r\n");
        sb.append(" */ \r\n");
        //实体部分
        sb.append("\r\n");
        sb.append("public class " + initcap(colnameToHump(tablename)) + " {\r\n");
        processAllAttrs(sb);//属性
        processAllMethod(sb);//get set方法
        sb.append("}\r\n");

        return sb.toString();
    }

    /**
     * 功能:生成所有属性
     *
     * @param sb
     */
    private void processAllAttrs(StringBuffer sb) {

        for (int i = 0; i < colnames.length; i++) {
            sb.append("\r\n");
            sb.append("   /**\r\n");
            sb.append("     * " + comment.get(colnames[i]) + "\r\n");
            sb.append("     */ \r\n");
            sb.append("\tprivate " + sqlType2JavaType(colTypes[i], colMap.get(colnames[i])) + " " + colnameToHump(colnames[i]) + ";\r\n");
        }

    }

    /**
     * 功能:生成getter,setter方法
     *
     * @param sb
     */
    private void processAllMethod(StringBuffer sb) {

        for (int i = 0; i < colnames.length; i++) {
            sb.append("\tpublic " + sqlType2JavaType(colTypes[i], colMap.get(colnames[i])) + " get" + initcap(colnameToHump(colnames[i])) + "(){\r\n");
            sb.append("\t\treturn " + colnameToHump(colnames[i]) + ";\r\n");
            sb.append("\t}\r\n");
            sb.append("\r\n");
            sb.append("\tpublic void set" + initcap(colnameToHump(colnames[i])) + "(" + sqlType2JavaType(colTypes[i], colMap.get(colnames[i])) + " " +
                    colnameToHump(colnames[i]) + "){\r\n");
            sb.append("\t\tthis." + colnameToHump(colnames[i]) + " = " + colnameToHump(colnames[i]) + ";\r\n");
            sb.append("\t}\r\n");
            sb.append("\r\n");
        }

    }

    /**
     * 功能:将数据库的字段改成驼峰命名的方式
     */
    public String colnameToHump(String colnames) {
        if (!hump) {
            return colnames;
        }
        String[] tf = colnames.split("_");
        String newColName = "";
        for (int i = 0; i < tf.length; i++) {
            tf[i] = initcap(tf[i]);
            newColName = newColName + tf[i];
        }
        return newColName;
    }

    /**
     * 功能:将输入字符串的首字母改成大写
     *
     * @param str
     * @return
     */
    private String initcap(String str) {
        if (!cap) {
            return str;
        }
        char[] ch = str.toCharArray();
        if (ch[0] >= 'a' && ch[0] <= 'z') {
            ch[0] = (char) (ch[0] - 32);
        }

        return new String(ch);
    }

    /**
     * 功能:获得列的数据类型
     *
     * @param sqlType
     * @param size
     * @return
     */
    private String sqlType2JavaType(String sqlType, Integer size) {
        if (sqlType.equalsIgnoreCase("int unsigned")) {
            if (size != null && size > 10) {
                return "long";
            }
            return "int";
        }
        if (sqlType.equalsIgnoreCase("bit")) {
            return "boolean";
        } else if (sqlType.equalsIgnoreCase("tinyint")) {
            return "byte";
        } else if (sqlType.equalsIgnoreCase("smallint")) {
            return "short";
        } else if (sqlType.equalsIgnoreCase("int")) {
            if (size != null && size > 10) {
                return "long";
            }
            return "int";
        } else if (sqlType.equalsIgnoreCase("bigint")) {
            return "long";
        } else if (sqlType.equalsIgnoreCase("float")) {
            return "float";
        } else if (sqlType.equalsIgnoreCase("decimal") || sqlType.equalsIgnoreCase("numeric")
                || sqlType.equalsIgnoreCase("real") || sqlType.equalsIgnoreCase("money")
                || sqlType.equalsIgnoreCase("smallmoney")) {
            return "double";
        } else if (sqlType.equalsIgnoreCase("varchar") || sqlType.equalsIgnoreCase("char")
                || sqlType.equalsIgnoreCase("nvarchar") || sqlType.equalsIgnoreCase("nchar")
                || sqlType.equalsIgnoreCase("text")) {
            return "String";
        } else if (sqlType.equalsIgnoreCase("datetime")) {
            return "Date";
        } else if (sqlType.equalsIgnoreCase("image")) {
            return "Blod";
        }

        return null;
    }

    /**
     * 出口
     *
     * @param args
     */
    public static void main(String[] args) {
        //List<String> listName=Db.query("select table_name from information_schema.tables where table_schema=?",schema);
        List<String> tableNames = Arrays.asList("osc_ad_click_details","osc_ad_operate_logs");
        tableNames.stream().forEach(s -> {
            new GenEntityMysql(s);
        });

    }

}
     

代码中有三个小细节:

  1. private boolean cap = false;//是否首字母大写 ,可大写或不大写
  2. private boolean hump = false;//是否驼峰,可驼峰或不驼峰
  3. private Map<String, Integer> colMap = new HashMap<>();//列名-列名大小,int类型的长度有的也不长,但是这里希望能根据数据库设置的int类型长度动态的设置属性修饰是int还是long

up-cb75e9eaa1de29bd9e89615098279d6e245.png

up-834aad323dc01a24cc1feafc9bc12055071.png

up-733d409f620c156a30eb0ec4062cdce9eb5.png


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK