美文网首页MyBatis+SpringMVC+SpringBoot程序员我爱编程
Mybatis-generator自动生成代码工具嵌入Maven

Mybatis-generator自动生成代码工具嵌入Maven

作者: 李北北 | 来源:发表于2018-01-30 15:44 被阅读60次

    Maven项目中用了mybatis框架,因此自然的用到了代码生成工具mybatis-generator-core-1.3.2.jar。

    我们一开始的做法是配置好generatorConfig.xml文件后,打开cmd命令窗口进入到生成文件所在的子项目目录中,执行命令: mvn mybatis-generator:generate。
    这种生成方式的操作太麻烦了,除了要打开命令窗口进入生成目录运行命令,还要提前删除已经生成的的xml文件,如果你的dao层mapper文件中类继承了父接口,还要因为被覆盖而需要重新写入继承代码,总之就是挺麻烦的,于是花了点时间进行优化。

    下面一步步介绍实现过程。

    1、首先是看看我们的项目结构,我们生成的代码是在common子项目中的


    image.png

    2、pom.xml文件中引入下面的依赖(数据库驱动包,我们是mysql数据库,其他数据库引用对应的依赖就可以了)

    <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.38</version>
          <scope>compile</scope>
    </dependency>
    <dependency>
          <groupId>org.mybatis.generator</groupId>
          <artifactId>mybatis-generator-core</artifactId>
          <version>1.3.2</version>
     </dependency>
    <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
    </dependency>
    <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.8.10</version>
    </dependency>
    

    3、看下图,我们需要创建两个配置文件,log4j.properties放在src/main/java目录下,generatorConfig.xml放在src/main/resources目录下,后面附上两个文件代码

    image.png

    log4j.properties代码

    log4j.rootLogger=DEBUG, Console
    #Console
    log4j.appender.Console=org.apache.log4j.ConsoleAppender
    log4j.appender.Console.layout=org.apache.log4j.PatternLayout
    log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
    log4j.logger.java.sql.ResultSet=INFO
    log4j.logger.org.apache=INFO
    log4j.logger.java.sql.Connection=DEBUG
    log4j.logger.java.sql.Statement=DEBUG
    log4j.logger.java.sql.PreparedStatement=DEBUG
    

    myGeneratorConfig.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" >
    
    <!--
        生成数据库表对应文件说明:
        1、配置生成的表
        2、执行类 GeneratorSqlmapUtil
    -->
    
    <generatorConfiguration>
        
        <!-- 配置一个代码生成操作,如果生成的目录或是数据库不一样,只需要参考增加一个context节点即可 -->
        <context id="context1">
            
            <!-- 这里的type里写的是你的实现类的类全路径,注:如果不配置type属性,则会使用默认的CommentGenerator实现类 -->
            <commentGenerator>
                <!-- 去除自动生成的注释 -->
                <!-- <property name="suppressAllComments" value="true" /> -->
                
                <!-- 是否生成注释代时间戳-->
                <property name="suppressDate" value="true"/> 
            </commentGenerator>
            
            <!-- 配置数据库,driverClass请根据所使用的数据库配置 -->
            <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                            connectionURL="jdbc:mysql://xxx.xxx.xxx:3306/数据库名称?useUnicode=true&amp;characterEncoding=UTF-8&amp;zeroDateTimeBehavior=convertToNull&amp;allowMultiQueries=true"
                            userId="数据库用户名"
                            password="数据库登陆密码">
            </jdbcConnection>
    
            <javaTypeResolver >
                <property name="forceBigDecimals" value="false" />
            </javaTypeResolver>
            
            <!-- 配置实体类、example类生成的路径 -->
            <javaModelGenerator targetPackage="com.xxx.xxx.model.common" targetProject="src/main/java" />
            
            <!-- 配置mapper.xml文件生成的路径(注:此处的targetPackage只要在base/mybatis/后面设置上面类文件包路径中最后一个名称就可以了) -->
            <sqlMapGenerator targetPackage="base/mybatis/common" targetProject="src/main/resources" />
            
            <!-- 
                   配置mapper接口生成的路径, 此处必须配置在javaModelGenerator和sqlMapGenerator后面,不然会报错
                   并且为生成的接口添加一个父接口,此处配置的父接口多一个下划线,
                   以备生成后提示错误以引导手动去完成正确的接口继承(继承BaseMapper并且将泛型类设置为对应的实体类、example类,并且删除生成的方法) 
            -->
            <javaClientGenerator targetPackage="com.xxx.xxx.dao.common" type="XMLMAPPER" targetProject="src/main/java">
                <!-- <property name="rootInterface" value="com.xxx.xxx.dao.base.BaseMapper_" /> -->
            </javaClientGenerator>
            
            
            <!-- 配置生成的表格, 同时生成多张表可以配置多个<table>标签 -->
            <table schema="database" tableName="common_table1" />
            
        </context>
    </generatorConfiguration>
    

    4、在src/main/java目录下任意包创建两个java类,下面分别贴上代码并简单介绍。

    (1)GeneratorSqlmap.java类,该类主要是读取配置文件,对目标表已经生成的xml文件进行删除,对mapper文件进行备份、恢复,调用生成工具执行生成操作,具体过程请阅读下面的源码。

    package com.xxx.xxx.util.generator;
    
    
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    
    import org.aspectj.util.FileUtil;
    import org.mybatis.generator.api.MyBatisGenerator;
    import org.mybatis.generator.config.Configuration;
    import org.mybatis.generator.config.Context;
    import org.mybatis.generator.config.JavaClientGeneratorConfiguration;
    import org.mybatis.generator.config.JavaModelGeneratorConfiguration;
    import org.mybatis.generator.config.SqlMapGeneratorConfiguration;
    import org.mybatis.generator.config.TableConfiguration;
    import org.mybatis.generator.config.xml.ConfigurationParser;
    import org.mybatis.generator.internal.DefaultShellCallback;
    import org.springframework.util.ResourceUtils;
    
    import com.xxx.xxx.util.StringUtil;
    
    /**
     * 根据数据库表生成model、example、mapper.xml文件
     * @author 北北
     * @date 2017年12月8日下午3:30:54
     */
    public class GeneratorSqlmap {
        
        /**
         * 根据配置的数据库表生成源码
         * @author 北北
         * @date 2018年1月17日上午11:04:26
         * @throws Exception
         */
        public void generator() throws Exception{
    
            List<String> warnings = new ArrayList<String>();
            boolean overwrite = true;
            
            //读取配置文件
            File configFile = ResourceUtils.getFile("classpath:myGeneratorConfig.xml");
            ConfigurationParser cp = new ConfigurationParser(warnings);
            Configuration config = cp.parseConfiguration(configFile);
            
            //删除需要生成的xml文件
            this.deleteOldXmlFile(config);
            
            //对Mapper文件备份处理
            Map<String, String> mapperFileValue = this.backupMapperFile(config);
            
            //生成代码执行
            DefaultShellCallback callback = new DefaultShellCallback(overwrite);
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
            myBatisGenerator.generate(null);
            
            //恢复已经存在的Mapper文件
            this.recoverMapperFile(mapperFileValue);
        }
    
        /**
         *恢复已经存在的Mapper文件
         * @author 北北
         * @date 2018年1月17日下午4:13:22
         * @param mapperFileValue
         */
        private void recoverMapperFile(Map<String, String> mapperFileValue) {
            for (Entry<String, String> fileValue : mapperFileValue.entrySet()) {
                String filePath = fileValue.getKey();
                String content = fileValue.getValue();
                File file = new File(filePath);
                FileUtil.writeAsString(file, content);
            }
        }
    
        /**
         * 对已经生成过的Mapper文件进行缓存备份
         * @author 北北
         * @date 2018年1月17日下午4:59:02
         * @param config
         * @return
         */
        private Map<String, String> backupMapperFile(Configuration config) {
            List<Context> contextList = config.getContexts();
            Map<String, String> fileValueMap = new HashMap<>();
            for (Context context : contextList) {
                JavaClientGeneratorConfiguration mapperConfig = context.getJavaClientGeneratorConfiguration();
                String mapperProject = mapperConfig.getTargetProject();
                String mapperPackage = mapperConfig.getTargetPackage();
                List<TableConfiguration> tableList = context.getTableConfigurations();
                for (TableConfiguration table : tableList) {
                    //提取文件名
                    String fileName = table.getDomainObjectName();
                    if(fileName == null){
                        fileName = StringUtil.camelName(table.getTableName());
                    }
                    fileName += "Mapper.java";
                    
                    //将包中的.全部替换为/
                    mapperPackage = mapperPackage.replaceAll("\\.", "/");
                    String mapperPath = mapperProject + "/" + mapperPackage + "/" + StringUtil.upperCaseFirst(fileName);
                    File mapperFile = new File(mapperPath);
                    
                    //如果已经存在的Mapper文件,备份
                    if(mapperFile.exists()){
                        String content;
                        try {
                            content = FileUtil.readAsString(mapperFile);
                            fileValueMap.put(mapperPath, content);
                            System.out.println("备份文件:" + mapperFile);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            return fileValueMap;
        }
    
        /**
         * 删除旧的xml文件, 避免内容重复
         * @author 北北
         * @date 2018年1月17日下午3:51:35
         * @param config
         */
        private void deleteOldXmlFile(Configuration config) {
            List<Context> contextList = config.getContexts();
            for (Context context : contextList) {
                SqlMapGeneratorConfiguration sqlConfig = context.getSqlMapGeneratorConfiguration();
                String sqlProject = sqlConfig.getTargetProject();
                String sqlPackage = sqlConfig.getTargetPackage();
                List<TableConfiguration> tableList = context.getTableConfigurations();
                for (TableConfiguration table : tableList) {
                    //提取文件名
                    String fileName = table.getDomainObjectName();
                    if(fileName == null){
                        fileName = StringUtil.camelName(table.getTableName());
                    }
                    fileName += "Mapper.xml";
                    
                    //根据xml文件相对路径创建file对象
                    String xmlPath = sqlProject + "/" + sqlPackage + "/" + StringUtil.upperCaseFirst(fileName);
                    File xmlFile = new File(xmlPath);
                    
                    //如果已经存在的Xml文件, 删除
                    if(xmlFile.exists()){
                        xmlFile.delete();
                        System.out.println("删除文件:" + xmlPath);
                    }
                }
            }
        } 
    
    }
    

    (2)GeneratorSqlmapUtil.java 该类是入口主函数所在,里面调用了上面类中生成代码的方法。

    package com.xxx.xxx.util.generator;
    
    /**
     * 生成sql映射代码主程序
     * @author 北北
     * @date 2018年1月17日下午5:34:03
     */
    public class GeneratorSqlmapUtil {
        
        /**
         * 生成代码入口
         * @author 北北
         * @date 2018年1月17日下午5:35:49
         * @param args
         * @throws Exception
         */
        public static void main(String[] args) throws Exception {
            try {
                GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
                generatorSqlmap.generator();
            } catch (Exception e) {
                e.printStackTrace();
            }
            
        }
    }
    
    

    至此,只需要在generatorConfig.xml文件中配置好了需要生成的表及生成目录,就可以run GeneratorSqlmapUtil.java类来生成表对应的实体类、example类、mapper类、xml文件了。

    注:
    1、如果要提取数据库字段的注释作为生成实体类的注释,请参考文章:
    Mybatis-generator自动生成代码时候提取数据库的字段注释作为实体类字段、getter/setter方法的注释

    2、如果用的是intellij编辑器,会有一个生成路径的问题,具体描述及解决方法请参考文章:
    Mybatis-generator自动生成代码工具嵌入maven项目中,在eclipse和intellij中获取的路径不一样问题

    相关文章

      网友评论

        本文标题:Mybatis-generator自动生成代码工具嵌入Maven

        本文链接:https://www.haomeiwen.com/subject/gwpwoxtx.html