让myql中的数据库表自动生成javaBean的模板

不积跬步,无以至千里

问题所在

今天重构以前的代码,因为数据库有比较大的改动,所以需要写很多javaBean!

作为一个程序员,重复意味着没有效率,更意味着无聊,一旦无聊便没有想编程的欲望,代码质量肯定刷刷刷的下降,质量下降了就意味着重写。。。。

so,为了集中精力在业务逻辑的代码上,减少不必要的时间浪费,于是花了一点时间写了一个把数据库中表的字段自动映射到 javaBean 中。

需求说明

输入所生成 文件的存放路径、文件的名称(默认是表名)、包名(生成的是java文件,一定要指定包名)、是否使用lombok插件(考虑到自己实现getter/setter方法有一定的困难,直接借助lombok插件),判断每一个表中的字段的类型,生成一个标准的javaBean文件

实现

依赖

  1. jdk1.8
  2. mysql-connector-java 驱动包

实现方法

  1. 使用mysql-connector-java连接需要操作的数据库;
  2. 得到数据库中所有的表名;
  3. 根据表名和数据库名称得到表的字段以及字段的类型;
  4. 根据表名和字段的类型,生成目标文件最重要的部分内容;
  5. 一个创建文件并向文件输入内容的方法;
  6. 对上述方法进行封装!
  7. 测试+完工;
  8. 记录+完善。

假想的条件

  1. 数据库的表名使用 下划线区分各个单词 来命名,eg: registed_user , approved_user;
  2. 数据库中的字段也如同表名的命名一样;

show代码

文件结构说明

让myql中的数据库表自动生成javaBean的模板_第1张图片

ConnectionUtil.java

得到数据库的连接

package connection;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionUtil {
    public static Connection getConn(String dbName, String username, String password) {
        String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/"+dbName+"?useUnicode=true&characterEncoding=utf-8&useSSL=false";
        Connection conn = null;
        try {
            Class.forName(driver); 
            conn = (Connection) DriverManager.getConnection(url, username, password);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
}

MapperUtil.java

这里写的是上述需要封装的所有方法

package mapper;

import connection.ConnectionUtil;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.sql.*;
import java.util.*;

public class MapperUtil {
    private DatabaseMetaData databaseMetaData;
    Connection connection;

    public MapperUtil(String dbName, String username, String password) throws SQLException {
        connection = ConnectionUtil.getConn(dbName, username, password);
        databaseMetaData = connection.getMetaData();
    }

    /**
     * 只是文件名(不包含扩展名)
     * @param fileName 文件名称
     * @param dir 文件所处的目录
     * @param mainContent 文件的主要内容
     * @param isLombok 是否包含lombok常见的一些方法?包含:不包含
     */
    public void createFile(String fileName, String dir, String packagePath, String mainContent, boolean isLombok) throws Exception {
        if (fileName == null || fileName.trim().equals("") || dir == null || dir.trim().equals("")){
            throw new Exception("传入参数不正确");
        }
        /**
         * 1.首先检测是否有这个文件夹路径
         * 2.如果不存在则新建
         */
        File fileDir = new File(dir);
        if (!fileDir.exists()){
            fileDir.setWritable(true);
            fileDir.mkdirs();
        }

        /**
         * 如果没有出错,那么创建文件,这里统一创建java文件
         */
        File javaFile = new File(fileDir, fileName+".java");
        javaFile.createNewFile();
        
        /**
         * 向文件中输送内容
         * 使用
         */
        DataOutputStream dataOutputStream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(javaFile)));
        dataOutputStream.writeBytes("package " + packagePath + ";\n");
        dataOutputStream.writeBytes("\n");
        if (isLombok){
            dataOutputStream.writeBytes(
                    "import lombok.*;\n\n"+
                    "@Data\n" +
                    "@ToString\n" +
                    "@Builder\n" +
                    "@AllArgsConstructor\n" +
                    "@NoArgsConstructor\n");
        }
        dataOutputStream.writeBytes("public class " + fileName + "{\n");
        dataOutputStream.writeBytes(mainContent);
        dataOutputStream.writeBytes("}");
        dataOutputStream.close();
    }

    /**
     * 构造对应的字符串。
     * @param map
     * @return
     */
    public String generateString(Map<String, String> map){
        String result = "";
        Set set = map.entrySet();
        /**
         * 对map进行遍历
         */
        for(Iterator iter = set.iterator(); iter.hasNext();)
        {
            Map.Entry entry = (Map.Entry)iter.next();
            String key = (String)entry.getKey();

            //把字段的下划线去掉,下划线后一位变为大写
            StringBuilder sb = new StringBuilder(key);
            for (int i = 1; i < key.length(); i++) {
                if (i+1 < key.length() && key.substring(i,i+1).equals("_")){
                    sb.replace(i, i+2, key.substring(i+1,i+2).toUpperCase());
                }
            }

            String value = (String)entry.getValue();
            System.out.println("key: " + key + " sb: " + sb +" :" + value);
            result += "    private " + value + " " + sb + ";\n";
        }
        return result;
    }



    /**
     * 返回字段名称和属性
     * @param tableName
     * @return
     */
    public Map<String, String> getFiledAndType(String tableName) throws SQLException {
        if (tableName == null || tableName.trim().equals("")){return null;}

        ResultSet resultSet = connection.prepareStatement("select * from " + tableName).executeQuery();
        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
        //得到所有的列名信息
        int count = resultSetMetaData.getColumnCount();
        Map<String, String> map = new HashMap<String, String>();
        for (int i = 1; i <= count; i++) {
            String type = resultSetMetaData.getColumnTypeName(i);
            type = typeTransform(type);
            map.put(resultSetMetaData.getColumnName(i), type);
        }
        return map;
    }

    /**
     * 得到所有表的名称
     * @return 含有所有表名的列表
     */
    public List<String> getTableNames() throws SQLException {
        List<String> tables = new ArrayList<String>();
        ResultSet resultSet = databaseMetaData.getTables(null, null, "%", null);
        while (resultSet.next()){
            String tableName = resultSet.getString("TABLE_NAME");
            tables.add(tableName);
            System.out.println(tableName);
        }
        return tables;
    }

    /**
     * 类型转换: 目前针对常见的几个类型
     * @return
     */
    public String typeTransform(String sqlType){
        if (sqlType == null || sqlType.trim().equals("")){
            return null;
        }
        sqlType = sqlType.toLowerCase();
        if (matchFloatNumber(sqlType)){
            return "double";
        }else if (matchInt(sqlType)){
            return "int";
        }else if (matchString(sqlType)){
            return "String";
        }
        return "String";
    }

    public boolean match(String target, String[] datas) {
        if (target == null || "".equals(target.trim()) || datas.length == 0){
            return false;
        }
        for (String a:datas) {
            if (a.equals(target)){
                return true;
            }
        }
        return false;
    }

    public boolean matchString(String target){
        String[] datas = {"char", "varchar", "date", "text", "timestamp", "datetime", "tinytext", "longtext"};
        return match(target, datas);
    }

    public boolean matchFloatNumber(String target){
        String[] datas = {"float", "double"};
        return match(target, datas);
    }

    public boolean matchInt(String target){
        String[] datas = {"int", "tinyint"};
        return match(target, datas);
    }
}

MapperDo.java

封装MapperUtil.java当中存在的方法

package mapper;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class MapperDo {
    private String dbName;
    private String username;
    private String password;
    private String baseDir;
    private String packagePath;
    private boolean isLombok;
    MapperUtil mapperUtil;

    public MapperDo(String dbName, String username, String password) throws SQLException {
        this.dbName = dbName;
        this.username = username;
        this.password = password;
        mapperUtil = new MapperUtil(dbName, username, password);
    }

    /**
     * 创建单个文本文件
     * @param baseDir
     * @param packagePath
     * @param isLombok
     * @param tableName
     * @throws Exception
     */
    public void generateFileModel(String baseDir, String packagePath, boolean isLombok, final String tableName) throws Exception {
        List<String> list = mapperUtil.getTableNames();
        boolean isExist = list.stream().noneMatch((s) -> s.equals(tableName));
        if (isExist){
            return;
        }
        String fileName = toCamelCase(tableName);
        Map<String, String> map = mapperUtil.getFiledAndType(tableName);
        String mainContent = mapperUtil.generateString(map);
        mapperUtil.createFile(fileName, baseDir, packagePath, mainContent, true);
    }

    /**
     * 创建这个数据库中所有的模板文件、
     * @param baseDir
     * @param packagePath
     * @param isLombok
     */
    public void generateFileModels( String baseDir, String packagePath, boolean isLombok) throws Exception {
        List<String> list = mapperUtil.getTableNames();
        for (String tableName:list) {
            String fileName = toCamelCase(tableName);
            Map<String, String> map = mapperUtil.getFiledAndType(tableName);
            String mainContent = mapperUtil.generateString(map);
            mapperUtil.createFile(fileName, baseDir, packagePath, mainContent, true);
        }
    }

    public String toCamelCase(String s){
        if (s == null){
            return null;
        }
        /**
         * 1. 把全部转成小写
         * 2. 把下划线全部去掉
         * 3. 把下划线之后的一个字母变成大写
         * 4. 首个字母变成大写
         */
        StringBuilder sb = new StringBuilder(s.toLowerCase());
        for (int i = 1; i < sb.length(); i++) {
            if (i+1 < sb.length() && sb.substring(i,i+1).equals("_")){
                sb.replace(i, i+2, sb.substring(i+1,i+2).toUpperCase());
            }
        }
        sb.replace(0,1, s.substring(0,1).toUpperCase());
        return sb.toString();
    }
    /**
    *------------------此处省略getter/setter方法
    **/
}

Main.java

测试代码

package run;

import mapper.MapperDo;


public class Main {
    public static void main(String[] args) throws Exception {
        MapperDo mapperDo = new MapperDo("bonetest","root","root");
//测试生成数据库中所有表的javaBean     	
		mapperDo.generateFileModels("/home/liudong/code/evaluate_bone/src/test/java/cn/edu/cqupt/mis/evaluate_bone/test", "liudong", false);
//测试生成advices一个表的javaBean
     	mapperDo.generateFileModel("/home/liudong/code/evaluate_bone/src/test/java/cn/edu/cqupt/mis/evaluate_bone/test", "liudong", false,"advices");
    }
}

测试的效果图如下:

  1. 数据库的结构
    让myql中的数据库表自动生成javaBean的模板_第2张图片
  2. advices表的结构
    让myql中的数据库表自动生成javaBean的模板_第3张图片
  3. 首先执行Main.java方法中单独生成一个javaBean.java的方法 generateFileModel
    让myql中的数据库表自动生成javaBean的模板_第4张图片
    4.执行另一个生成所有表的javaBean方法generateFileModels
    让myql中的数据库表自动生成javaBean的模板_第5张图片

总结

代码和逻辑虽然简单,但是实现之后再次记录,就会温故而知新。
代码我会继续完善,希望有问题大家可以一起探讨探讨。

你可能感兴趣的:(让myql中的数据库表自动生成javaBean的模板)