package com.dk.mdm.generator;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;

/**
 * @desc   : mybatis_plus逆向工程类
 *           引入的目的：
 *           1.解决每一个模块都要写的增删改查基础操作，
 *           像insert、deleteById、updateById、disableById、selectById这些通用功能以后不需要再手写xml了，
 *           2.表加列了，只需要在对应的entity中加属性，而也不需要我们再去维护操作单表的xml（关联查询还是要改的），
 *           3.避免出现一些大小写的低级错误，统一代码规范。
 *           4.让开发人员有更多的时间去转注于业务，避免重复无意义的工作。
 *
 *           但是mybatis_plus只针对于单表操作，引入其目的，是为了提升开发效率，它并不能代替开发人员去完成所有工作，
 *           比如关联分页条件查询、子查询、分组查询、多主键问题、和具体的业务还是需要我们去自行完成的。
 *           它的定位只是一个插件，不能作为一个完整的orm框架解决方案。没有完美的工具，择其善者而从之，其不善者而改之。
 * @author : 张潇木
 * @date   : 2022-3-1 12:53
 */
@SpringBootTest
@RunWith(SpringRunner.class)//不加无法注入Mapper
@Slf4j
public class Generator {


    /**
     * @desc   : 针对单表，自动生成增删改查sql、xml、mapper接口、service方法、controller接口
     * @author : 张潇木
     * @date   : 2022-3-1 13:03
     */
    @Test
    public void generate(){

        //构建一个生成器对象
        AutoGenerator mpg = new AutoGenerator();

        //1、全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");    //获取当前目录
        gc.setOutputDir(projectPath+"/src/main/java");          //输出到哪个目录
        gc.setAuthor("宋扬");                                    //作者
        gc.setOpen(false);                                      //是否打开目录
        gc.setFileOverride(false);                              //是否覆盖
        gc.setServiceName("%sService");                         //去Service的I前缀
        gc.setServiceImplName("%sService");
        gc.setIdType(IdType.AUTO);							    //主键策略
        gc.setBaseResultMap(true);							    //SQL 映射文件
        gc.setBaseColumnList(true);							    //SQL 片段
        gc.setDateType(DateType.ONLY_DATE);                     //时间类型
        gc.setSwagger2(true);                                   //Swagger
        mpg.setGlobalConfig(gc);

        //2、设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUsername("dkic_b");
        dsc.setPassword("dk");
        dsc.setUrl("jdbc:postgresql://dkdev.dkiboss.com:15000/dkic_dev_b1");
        dsc.setSchemaName("dkic_b");
        dsc.setDriverName("org.postgresql.Driver");
        dsc.setDbType(DbType.POSTGRE_SQL);
        mpg.setDataSource(dsc);

        //3、包的配置
        PackageConfig pc = new PackageConfig();
//        pc.setModuleName("task");                  //模块包名
        pc.setParent("com.dk.mdm");        //父包路径
        pc.setEntity("model.pojo.ivt");                     //实体层路径
        pc.setMapper("mapper.ivt");                 //mapper层路径
        pc.setXml("mapper.ivt");                       //xml层路径
        pc.setServiceImpl("service.ivt");                   //业务层路径
        pc.setController("controller.ivt");             //控制层路径
        //app相关路径
//        pc.setEntity("model.app.pojo.pset");                     //实体层路径
//        pc.setMapper("mapper.app.pset");                 //mapper层路径
//        pc.setXml("mapper.app.pset");                       //xml层路径
//        pc.setServiceImpl("service.app.pset");                   //业务层路径
//        pc.setController("controller.app.pset");             //控制层路径
        mpg.setPackageInfo(pc);

        //4、策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setTablePrefix("t_psi");                                             //表名前缀
        strategy.setInclude("t_psi_transfer");                                    //设置要映射的表名,只需改这里即可,可以是一个数组，一次性生成多张表。
        strategy.setInclude("t_psi_transfer_item");
        strategy.setNaming(NamingStrategy.underline_to_camel);                      //转驼峰
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);                //字段下划线转驼峰
        strategy.setEntityLombokModel(true);                                        //是否使用lombok开启注解
        strategy.setSuperEntityClass("com.dk.common.pojo.PageInfo");        //实体基类
        strategy.setSuperControllerClass("com.dk.common.controller.BaseController");        //实体基类
        strategy.setSuperServiceImplClass("com.dk.common.service.BaseService");    //service基类
        strategy.setSuperMapperClass("com.dk.common.mapper.BaseMapper");      //mapper基类
//        strategy.setVersionFieldName("version");                                    //乐观锁配置
        strategy.setRestControllerStyle(true);                                      //开启驼峰命名
        strategy.setControllerMappingHyphenStyle(true);                             //localhost:8080/hello_id_2
        //        逻辑删除标识，逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案，但实际就是删除。
        //        如果你需要再查出来就不应使用逻辑删除，而是以一个状态去表示。
        //        硬写：yml中logic-not-delete-value: 1 or value_flag=0
        //        如： 员工离职，账号被锁定等都应该是一个状态字段，此种场景不应使用逻辑删除。
        //        若确需查找删除数据，如老板需要查看历史所有数据的统计汇总信息，请单独手写sql。
//        strategy.setLogicDeleteFieldName("flg_del");                         //逻辑删除字段，所有的查询都会自动带上value_flag=1这个条件。

        // 自动填充配置
        TableFill createTime = new TableFill("op_create_time", FieldFill.INSERT);          //创建时间
//        TableFill updateTime = new TableFill("op_update_time", FieldFill.INSERT_UPDATE);   //更新时间
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(createTime);
//        tableFills.add(updateTime);
        strategy.setTableFillList(tableFills);
        mpg.setStrategy(strategy);

        //5、 自定义模板配置 放置自己项目的 src/main/resources/mp_templates 目录下, 默认名称一下可以不配置，也可以自定义模板名称
        TemplateConfig tc = new TemplateConfig();
        tc.setEntity("/mp_templates/entity.java");
        tc.setXml("/mp_templates/mapper.xml")		        				        // 设置生成xml的模板
                .setEntity("/mp_templates/entity.java")		        			// 设置生成entity的模板
                .setMapper("/mp_templates/mapper.java")		        			// 设置生成mapper的模板
                .setController("/mp_templates/controller.java")       			// 设置生成service的模板
                .setService(null)							// 设置生成serviceImpl的模板
                .setServiceImpl("/mp_templates/serviceImpl.java");				// 设置生成controller的模板
        mpg.setTemplate(tc);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());		    // 选择 freemarker引擎，注意 pom 依赖必须有！
        mpg.execute();//执行
    }

}
