代码生成器官方文档

代码生成器基本配置

代码生成器官方示例

如果需要更多个性化的生成请详阅官方文档!

这里针对自己项目的配置做一些解析:

1.全局配置

// 代码生成器
AutoGenerator mpg = new AutoGenerator();
 
// 全局配置
GlobalConfig gc = new GlobalConfig();
//生成文件放置位置
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");
//需要修改的地方
gc.setAuthor("xiaochen");
gc.setBaseResultMap(true);
gc.setBaseColumnList(true);
gc.setOpen(false);
//是否覆盖已有的文件
//gc.setFileOverride(false);
mpg.setGlobalConfig(gc);

全局配置具体有哪些参数可配置见GlobalConfig类。

具体我们关注几个字段:

outputDir:输出目录

DateType:时间类型对应策略,默认值:TIME_PACK使用Java 8的新时间类型(如LocalDateTime)。具体能不能使用Java 8的时间类型需要Mysql驱动支持,项目中我升级了驱动到最低支持Java 8时间的驱动的版本5.1.37

由于项目使用了阿里巴巴的连接池Druid,所以也针对连接池升级了版本1.1.20,根据官方文档显示1.1.18开始可以支持Java8的时间

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.20</version>
</dependency>    
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.37</version>
    <scope>runtime</scope>
</dependency>

author:开发人员,对应生成文件的头部作者标签。创建时间工具会自动生成不需要配置

baseResultMap:建议开启,能够生成类似下图的全字段映射的结果,可以把返回结果和model字段一一映射,你可以根据全字段剔除或者copy出一个新的部分字段的ResultMap。使用方式谷歌百度。

baseResultMap
baseResultMap

baseColumnList:建议开启,便捷生成通用查询结果列,你可以根据全字段剔除或者copy出一个新的部分字段的Column_List。使用方式谷歌百度。

baseColumnList
baseColumnList

fileOverride:是否覆盖已有文件,官方是写false,但是实际上生成的文件测试结果是会被覆盖重写

实体类命名采用默认命名

2.数据源配置

// 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        Props props = new Props("xxxx.properties");
        dsc.setUrl(props.getStr("jdbc.url"));
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername(props.getStr("jdbc.username"));
        dsc.setPassword(props.getStr("jdbc.password"));
        mpg.setDataSource(dsc);

配置数据库信息,为了能够快捷读取properties文件,我引入hutool工具类来快速读取,因为这个是一个main方法,不能使用Spring的东东!

3.包配置

// 包配置
        PackageConfig pc = new PackageConfig();
        String moduleName = scanner("模块名");
        pc.setModuleName(moduleName);
        pc.setEntity("model");
        pc.setParent("path");
        mpg.setPackageInfo(pc);

moduleName:输入模块名,也就是包名

parent:上面包名的父级

entity:因为默认是叫entity,不符合我们项目的风格,所以自定义了实体类存放包名叫model

4.自定义配置

// 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = Maps.newHashMap();
                map.put("mapper", "path.mapper." + moduleName);
                map.put("model", "path.model." + moduleName);
                this.setMap(map);
            }
        };
        List<FileOutConfig> focList = generateFileOutConfigs(projectPath, pc);
 
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);
        mpg.setTemplate(new TemplateConfig().setXml(null)
                .setController(null)
                .setService(null)
                .setServiceImpl(null)
                .setMapper(null)
                .setEntity(null));
private static List<FileOutConfig> generateFileOutConfigs(String projectPath, PackageConfig pc) {
        List<FileOutConfig> focList = Lists.newArrayList();
        focList.add(new FileOutConfig("/template/CustomMapper.xml.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输入文件名称
                return projectPath + "/src/main/resources/mybatis/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
 
        focList.add(new FileOutConfig("/template/CustomMapper.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输入文件名称
                return projectPath + "/src/main/java/path/mapper/" + pc.getModuleName() + "/" + tableInfo.getEntityName() + "Mapper" +
                        StringPool.DOT_JAVA;
            }
        });
 
        focList.add(new FileOutConfig("/template/CustomEntity.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输入文件名称
                return projectPath + "/src/main/java/path/model/" + pc.getModuleName() + "/" + tableInfo.getEntityName() +
                        StringPool.DOT_JAVA;
            }
        });
        return focList;
    }

项目里我只生成xml,模型,mapper接口,没有生成控制层和服务层,因为包办这两个就有点不太灵活(当然你有需求也可以生成这两个类)。但是官方的模板没办法符合我们想要的结果,因为生成文件的包名路径的问题,所以不采用官方的几个模板,而是稍微做了一些自定义,把包路径做了自定义,使得生成文件里的包的路径是model.包名.类名而不是包名.model.类名

所以下图的这段代码是屏蔽生成这些文件

屏蔽不需要生成的文件
屏蔽不需要生成的文件

generateFileOutConfigs这个方法就是自定义生成的文件包含xml,mapper,model

自定义生成文件的包路径,因为官方为了满足大部分的需求,所以模板不一定满足一些项目的需求,所以官方也有这样的自定义的方式。下图就是自定义模板里的字段

参见官方:自定义属性注入

自定义属性
自定义属性

模板自定义属性的配置
模板自定义属性的配置

5.策略配置

// 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setInclude(scanner("表名"));
        strategy.setEntityTableFieldAnnotationEnable(false);
        mpg.setStrategy(strategy);
        // 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());

详细的策略属性见StrategyConfig类

naming:数据库表映射到实体的命名策略,开启驼峰映射

columnNaming:数据库表字段映射到实体的命名策略, 未指定按照 naming 执行。这里也是开启驼峰映射

entityLombokModel:【实体】是否为lombok模型(默认 false)。因为项目里引进了lombok插件,所以这里也是truename生成的文件会自动加上生成@Data那些注解

include:需要包含的表名,允许正则表达式(与exclude二选一配置)。即要生成文件的表名

entityTableFieldAnnotationEnable:是否生成实体时,生成字段注解。即字段头上的@TableField("is_display")

这里我设置为false不生成,如果你在Mybatis配置了自动开启驼峰映射(mapUnderscoreToCamelCase)就不需要加,不然的话需要加上这些注解才能保证BaseMapper的自带的方法能够使用

参见: mapUnderscoreToCamelCase参数

mapUnderscoreToCamelCase
mapUnderscoreToCamelCase

所以Mybatis Plus为了能够方便使用是把这个属性默认设置为true,这里有一个踩坑的地方:

如果你在sql上写的是select \* from....然后在想通过resultMap的映射去掉那些没有指定映射的字段,一旦mapUnderscoreToCamelCasetrue,那么这个属性会影响resultMap的返回结果,导致只要是能符合驼峰映射的字段都会被赋值,所以你可能会看到很多属性莫名其妙被赋值且你还不知道为什么他那么智能能够找到这个字段,准确赋值

6.执行

mpg.execute();

至此就能够生成我们想要的3个文件了!