Mybatis-generator自动生成代码工具嵌入Maven项目中,实现一键生成数据库表对应的java、xml文件

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中获取的路径不一样问题

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,681评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,710评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,623评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,202评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,232评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,368评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,795评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,461评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,647评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,476评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,525评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,226评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,785评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,857评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,090评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,647评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,215评论 2 341

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,422评论 0 4
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,570评论 18 139
  • 文|四月默 梁山伯是憨厚老实、知世故而不世故,祝家九妹一颗心都扑在他身上。 月老庙躲雨的那场邂逅,月老就为二人拉了...
    四月默阅读 7,290评论 119 158
  • 我想要一座房子,面朝大海,春暖花开。但我并不想从明天起,喂马,劈柴。
    张琦zzq阅读 145评论 0 0
  • 文字,这个事儿 其实我不行, 虽然,男人不能说自己不行, 那我只能手动滑稽了。 主要是,每次开头我都能想半天,却又...
    谁是摆渡人阅读 329评论 1 4