mybatis学习:相关代码自动生成(Model、Mapper、Service)

初学mybatis,然后看到他的这种运作方式,想想数据库的20几个表格,都要生成Mapper.xml、dao类、entity类、service类、web页面,20*5立马头大了,毕竟重复工作很无聊还很低效!!

于是开始百度,对于java我比较小白,但是编程的思想告诉我,重复性的劳动是给程序干的,果然找到相关的文章,这些东西是可以自动生成的,当然其中也走了弯路,最开始的想法是能连接数据库,能读数据表的结构信息(字段名、类型这些的)就自己组合下逻辑就可以自动生成实体类,毕竟这个类是最麻烦的,要把表里的字段都映射过来。

于是有了下面第一个版本,这个项目依赖很少,也不是最终我需要的,只当是练手吧,重点在后面

package com.wwt.robot;

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.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Date;

public class GenOnlyModel {
    private final String authorName = "wwt";                            //作者名字
    private final String packageOutPath = "com.wwt.robot.entity";       //指定实体生成所在包的路径
    private final String classImplements = "implements Serializable";   //类的继承关系
    private String tablename;                                           //表名
    private String[] colnames;                                          //列名数组
    private String[] colTypes;                                          //列名类型数组
    private int[] colSizes;                                             //列名大小数组
    private boolean f_util = false;                                     //是否需要导入包java.util.*
    private boolean f_sql = false;                                      //是否需要导入包java.sql.*
    private boolean f_serializable = true;                              //是否需要导入包java.io.Serializable
    private boolean f_bigDecimal = true;                                //是否需要导入包java.math.BigDecimal

    //数据库连接(这个是MySQL5.XXX版本的JDBC,用8.XXX版本需要修改)
    private static final String URL = "jdbc:mysql://localhost:3306/wwtclrobot?useUnicode=true&characterEncoding=UTF-8";
    private static final String NAME = "root";
    private static final String PASS = "123456";
    private static final String DRIVER = "com.mysql.jdbc.Driver";

    /*
     * 构造函数
     */
    public GenOnlyModel(String tablename) {
        //表名
        this.tablename = tablename;
        //创建连接
        Connection con = null;
        //查要生成实体类的表
        String sql = "select * from " + tablename;
        PreparedStatement pStemt = null;
        try {
            try {
                Class.forName(DRIVER);
            } catch (ClassNotFoundException e1) {
                // TODO Auto-generated catch block
                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++) {
                colnames[i] = rsmd.getColumnName(i + 1);
                colTypes[i] = rsmd.getColumnTypeName(i + 1);

                if (colTypes[i].equalsIgnoreCase("datetime") || colTypes[i].equalsIgnoreCase("date")) {
                    f_util = true;
                }
                if (colTypes[i].equalsIgnoreCase("image") || colTypes[i].equalsIgnoreCase("text")) {
                    f_sql = true;
                }
                colSizes[i] = rsmd.getColumnDisplaySize(i + 1);
            }

            String content = parse(colnames, colTypes, colSizes);

            try {
                File directory = new File("");
                String outputPath = directory.getAbsolutePath() + File.separator + "entity" + File.separator + "src"  + File.separator + "main" + File.separator + "java" + File.separator + this.packageOutPath.replace(".", File.separator) + File.separator + initcap(tablename) + ".java";
                System.out.println(String.format("输出路径-%s", outputPath));
                File entityFile = new File(outputPath);
                if (!entityFile.exists()) {
                    entityFile.createNewFile();
                }
                FileWriter fw = new FileWriter(outputPath);
                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) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    /**
     * 功能:生成实体类主体代码
     *
     * @param colnames
     * @param colTypes
     * @param colSizes
     * @return
     */
    private String parse(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");
        }
        if (f_serializable) {
            sb.append("import java.io.Serializable;\r\n");
        }
        if (f_bigDecimal) {
            sb.append("import java.math.BigDecimal;;\r\n");
        }
        sb.append("\r\n");
        //注释部分
        sb.append("/**\r\n");
        sb.append(" * " + tablename + " BOJO\r\n");
        sb.append(" * POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称。\r\n");
        sb.append(" * 其中有一些属性及其getter、setter方法的类,没有业务逻辑,有时可以作为VO(value-object)或DTO(Data Transfer Object)来使用。不允许有业务方法,也不能携带connection之类的方法。\r\n");
        sb.append(" * " + new Date() + " " + this.authorName + "\r\n");
        sb.append("*/ \r\n");
        //实体部分
        sb.append("public class " + initcap(tablename) + " "+ classImplements + " {\r\n");
        processAllAttrs(sb);            //属性
        processAllMethod(sb);           //get set方法
        processToString(sb);            //输出打印字符串
        sb.append("}\r\n");

        //System.out.println(sb.toString());
        return sb.toString();
    }

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

        for (int i = 0; i < colnames.length; i++) {
            sb.append("\tprivate " + sqlType2JavaType(colTypes[i]) + " " + colnames[i] + ";\r\n");
        }
    }

    /**
     * 功能:生成所有方法
     *
     * @param sb
     */
    private void processAllMethod(StringBuffer sb) {
        sb.append("\r\n");
        for (int i = 0; i < colnames.length; i++) {
            sb.append("\tpublic void set" + initcap(colnames[i]) + "(" + sqlType2JavaType(colTypes[i]) + " " +
                    colnames[i] + "){\r\n");
            sb.append("\t\tthis." + colnames[i] + "=" + colnames[i] + ";\r\n");
            sb.append("\t}\r\n");
            sb.append("\tpublic " + sqlType2JavaType(colTypes[i]) + " get" + initcap(colnames[i]) + "(){\r\n");
            sb.append("\t\treturn " + colnames[i] + ";\r\n");
            sb.append("\t}\r\n");
        }
    }

    /**
     * 功能:生成打印输出字符串的重载函数
     */
    private void processToString(StringBuffer sb) {
        sb.append("\r\n");
        sb.append("\t@Override\r\n");
        sb.append("\tpublic String toString() {\r\n");
        sb.append("\t\treturn \"" + initcap(tablename) + "{\" +\r\n");
        for (int i = 0; i < colnames.length; i++) {
            if(sqlType2JavaType(colTypes[i]) == "byte" || sqlType2JavaType(colTypes[i]) == "short" ||
                    sqlType2JavaType(colTypes[i]) == "int" || sqlType2JavaType(colTypes[i]) == "long" ||
                    sqlType2JavaType(colTypes[i]) == "float" || sqlType2JavaType(colTypes[i]) == "double" ||
                    sqlType2JavaType(colTypes[i]) == "boolean" || sqlType2JavaType(colTypes[i]) == "BigDecimal" ) {
                sb.append("\t\t\t\"" + colnames[i] + "=\" + " + colnames[i] + " +\r\n");
            } else if(sqlType2JavaType(colTypes[i]) == "char" || sqlType2JavaType(colTypes[i]) == "String")
            {
                sb.append("\t\t\t\"" + colnames[i] + "=\'\" + " + colnames[i] + " + '\\'' +\r\n");
            } else{
                sb.append("\t\t\t\"" + colnames[i] + "=\" + " + colnames[i] + " +\r\n");
            }
        }
        sb.append("\t\t'}';\r\n");
        sb.append("\t}\r\n");
    }

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

    /**
     * 功能:获得列的数据类型
     *
     * @param sqlType
     * @return
     */
    private String sqlType2JavaType(String sqlType) {

        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")) {
            return "int";
        } else if (sqlType.equalsIgnoreCase("bigint")) {
            return "long";
        } else if (sqlType.equalsIgnoreCase("float")) {
            return "float";
        } else if (sqlType.equalsIgnoreCase("decimal")) {
            return "BigDecimal";
        }else if (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") || sqlType.equalsIgnoreCase("date")) {
            return "Date";
        } else if (sqlType.equalsIgnoreCase("image")) {
            return "Blod";
        }

        return null;
    }

    public static void main(String[] args) {
        new GenOnlyModel("Goods");
    }
}

这个方式只能生成最复杂的一项,数据表对应的实体类,其它的需要自己去写,不甘心!!! 

写出来就是为了练习而已,然后开始继续找,一个工具吸引了我:

Mybatis generator自动生成dao,mapper,mapperXML

官网地址:MyBatis Generator Core

这个官网有例子,百度上面相关的教程也比较多,具体的我就不写了,有兴趣的自己去看看吧!

然后还是百度看看配置教程折腾了两天,搞定了,可以一次生成三个文件(模型+接口+映射),后来什么原因没用用这个,是因为除了这个另外还有service跟web两个文件要写,这个不能自动生成,只生成前面的东西,我20几个表,一次全做出来,不生成后面的文件,整个程序是编译不过的,没法调试,非常讨厌这种感觉,我的原则是不管对错,程序先要能编译,能跑起来,然后再来找问题,还有一个就是这个生成的文件没法自定义名称,后面一个一个自己改,还是有点小麻烦。

原本可以一个表一个表的处理,后面想想既然java是分层开发的,那还是先一层一层的处理完,再考虑上面的东西,数据库到java的映射一次搞定,于是又开始找,这次没有找到现成的东西,但是找到了一个类“tk.mybatis.mapper”借用这个类可以实现我的要求,于是又花费了三天时间,写个生成工具,现在已经能用了,我已经放到GitHub上,刚搞完,有兴趣的可以自己下载试试:

mybatis-CodeGenerator: 代码生成器,根据数据表名称生成对应的Model、Mapper、Service简化开发 

期间很多坑一路踩过来,很有意思,也觉得收获挺多,有时间再写。

这里记录几个东西:

已经能实现功能之后提交了开源,然后尝试升级相关依赖

!、JDBC 5.XXX的 mysql-connector-java 升级到8.0.27版本,然后不能自动生成文件了,提示是JDBC链接方式有了改变,程序中调整了JDBC连接字符串,问题解决

2、mybatis-generator-core这个依赖升级到1.4.0之后不能用了,目前没时间解决,毕竟工具是用来方便干活的,已经放在这个上面的时间不少了,降级回1.3.5,继续升级其它的

3、hibernate-validator 尝试升级到7.0.2.Final,发现javax.validation.Valid依赖不能用了,后面降级到6.2.0.Final又可以使用,考虑到暂时没有其它地方需要使用到Hibernate-validator,这个类升级到高版本时应该已经经不再包含或者调用javax.validation-api,导致升级之后项目依赖反而不能正常使用 所以干脆去掉这个类的依赖,直接使用javax.validation-api的最高版本,测试功能正常!

这里也给我一个自己一个忠告:尽量是需要什么类用什么类,不要因为某个大类引用或者包含了你要用的几个东西,就直接拿来用,虽然这样开发会比较省事,不过将来的依赖一旦出现问题之后处理起来会比较麻烦。那天别人升级了,不包含你要引用的依赖了,你都不知道问题出在哪里~

用最小的类,能够在这个类升级的时候很容易的尝试升级他,影响的面积也小!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Mybatis是一个优秀的ORM框架,可以帮助我们快速地进行数据库操作。而Mybatis代码自动生成工具可以帮助我们快速生成Java类和Mybatis对应的SQL语句,从而提高开发效率。以下是两种常用的Mybatis代码自动生成工具: 1. Mybatis Generator Mybatis Generator是Mybatis官方提供的代码自动生成工具,可以根据数据库表生成Java类和Mybatis对应的SQL语句。使用Mybatis Generator需要编写一个XML配置文件,指定数据库连接信息、生成的Java类和SQL语句的包名、生成的表等信息。以下是一个简单的Mybatis Generator配置文件示例: ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="DB2Tables" targetRuntime="MyBatis3"> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test" userId="root" password="root"> </jdbcConnection> <javaModelGenerator targetPackage="com.example.model" targetProject="src/main/java"> </javaModelGenerator> <sqlMapGenerator targetPackage="com.example.mapper" targetProject="src/main/resources"> </sqlMapGenerator> <javaClientGenerator type="XMLMAPPER" targetPackage="com.example.mapper" targetProject="src/main/java"> </javaClientGenerator> <table tableName="user"></table> </context> </generatorConfiguration> ``` 2. Mybatis-Plus Generator Mybatis-Plus是Mybatis的增强工具,在Mybatis的基础上提供了更多的功能。Mybatis-Plus Generator是Mybatis-Plus提供的代码自动生成工具,可以快速生成Entity、MapperMapper XML、Service、Controller等各个模块的代码。使用Mybatis-Plus Generator需要编写一个Java类,指定数据库连接信息、生成的Java类和SQL语句的包名、生成的表等信息。以下是一个简单的Mybatis-Plus Generator配置类示例: ```java public class CodeGenerator { public static void main(String[] args) { AutoGenerator mpg = new AutoGenerator(); // 数据源配置 DataSourceConfig dsc = new DataSourceConfig(); dsc.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8"); dsc.setDriverName("com.mysql.jdbc.Driver"); dsc.setUsername("root"); dsc.setPassword("root"); mpg.setDataSource(dsc); // 包配置 PackageConfig pc = new PackageConfig(); pc.setParent("com.example"); pc.setEntity("model"); pc.setMapper("mapper"); pc.setXml("mapper.xml"); pc.setService("service"); pc.setServiceImpl("service.impl"); pc.setController("controller"); mpg.setPackageInfo(pc); // 策略配置 StrategyConfig strategy = new StrategyConfig(); strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); strategy.setEntityLombokModel(true); strategy.setRestControllerStyle(true); strategy.setInclude("user"); mpg.setStrategy(strategy); // 执行生成 mpg.execute(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值