从零搭建开发脚手架 Spring Boot集成Mybatis-plus之一


类似 TkMybatis

官网地址:

https://baomidou.com/

简介

MyBatis-Plus (简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

愿景

我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。

img

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

框架结构

framework

依赖集成

全新的 MyBatis-Plus 3.0 版本基于 JDK8,提供了 lambda 形式的调用,所以安装集成 MP3.0 要求 JDK 8+

依赖

Spring Boot 与MP 版本不清楚的,可以看下mybatis-plus-boot-starter中依赖的Boot版本

引入 Spring Boot Starter 父工程:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.3</version>
    <relativePath/>
</parent>

引入 spring-boot-starterspring-boot-starter-testmybatis-plus-boot-starterh2 依赖:

Latest Version: 传送门

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.2</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

配置

application.yml 配置文件中添加 H2 数据库的相关配置:

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/laker?serverTimezone=GMT%2B8&characterEncoding=utf8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver

在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:

@SpringBootApplication
@MapperScan("com.laker.demo.mapper")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(QuickStartApplication.class, args);
    }
}

编码

编写实体类 User.java(此处使用了 Lombok简化代码)

@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

编写Mapper类 UserMapper.java

public interface UserMapper extends BaseMapper<User> {
}

开始使用

添加测试类,进行功能测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleTest {
    @Autowired
    private UserMapper userMapper;
    @Test
    public void testSelect() {
		List<User> userList = userMapper.selectList(
        			new QueryWrapper<User>()
                		.lambda()
                		.ge(User::getAge, 18)
		);
        // SELECT * FROM user WHERE age >= 18
    }
}

到这里入门demo就够了,以下皆为扩展高级功能.

核心功能

代码生成器

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

自定义模板有哪些可用参数?GithubAbstractTemplateEngine 类中方法 getObjectMap 返回 objectMap 的所有值都可用。

演示效果图

relationship

添加依赖

MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖:

  • 添加 代码生成器 依赖(必选)

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.4.2</version>
    </dependency>
    
  • 添加 模板引擎 依赖,MyBatis-Plus 支持 Velocity(默认)、Freemarker、Beetl,用户可以选择自己熟悉的模板引擎,如果都不满足您的要求,可以采用自定义模板引擎。(必选其中的一个)

    Velocity(默认):

    <dependency>
        <groupId>org.apache.velocity</groupId>
        <artifactId>velocity-engine-core</artifactId>
        <version>2.3</version>
    </dependency>
    

    Freemarker:

    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.31</version>
    </dependency>
    

    Beetl:

    <dependency>
        <groupId>com.ibeetl</groupId>
        <artifactId>beetl</artifactId>
        <version>3.3.2.RELEASE</version>
    </dependency>
    

    注意!如果您选择了非默认引擎,需要在 AutoGenerator 中 设置模板引擎。

    AutoGenerator generator = new AutoGenerator();
    
    // set freemarker engine
    generator.setTemplateEngine(new FreemarkerTemplateEngine());
    
    // set beetl engine
    generator.setTemplateEngine(new BeetlTemplateEngine());
    
    // set custom engine (reference class is your custom engine class)
    generator.setTemplateEngine(new CustomTemplateEngine());
    
    // other config
    ...
    

编码

// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {

    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }

    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        String projectPath = globalConfig(mpg);

        // 数据源配置
        dataSourceConfig(mpg);

        // 生成代码包配置
        PackageConfig pc = packageConfig(mpg);

        diyConfig(mpg, projectPath, pc);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        // 配置自定义输出模板
        //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        // templateConfig.setEntity("templates/entity2.java");
        // templateConfig.setService();
        // templateConfig.setController();

        // 这里默认的xml生成的位置与mapper在一个目录,不实用,改为diyConfig中 自定义到 resources/mapper下
        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        strategyConfig(mpg, pc);

        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }

    private static void diyConfig(AutoGenerator mpg, String projectPath, PackageConfig pc) {
        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        /*
        cfg.setFileCreate(new IFileCreate() {
            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                // 判断自定义文件夹是否需要创建
                checkDir("调用默认方法创建的目录,自定义目录用");
                if (fileType == FileType.MAPPER) {
                    // 已经生成 mapper 文件判断存在,不想重新生成返回 false
                    return !new File(filePath).exists();
                }
                // 允许生成模板文件
                return true;
            }
        });
        */
        // 自定义输出文件
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);
    }

    private static void strategyConfig(AutoGenerator mpg, PackageConfig pc) {
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        // "你自己的父类实体,没有就不用设置!"
//        strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
        // 【实体】是否为lombok模型(默认 false)
        strategy.setEntityLombokModel(true);
        // 生成 @RestController 控制器
        strategy.setRestControllerStyle(true);
        // 公共父类 "你自己的父类控制器,没有就不用设置!"
//        strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
        // 写于父类中的公共字段
//        strategy.setSuperEntityColumns("id");
        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix(pc.getModuleName() + "_");
        mpg.setStrategy(strategy);
    }

    private static PackageConfig packageConfig(AutoGenerator mpg) {
        PackageConfig pc = new PackageConfig();
        // sys 父包模块名
        pc.setModuleName(scanner("模块名"));
        // 父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
        pc.setParent("com.laker.demo");

        /**
         * 上面的代码生成位置及包名称
         * com.laker.demo.sys
         */
        mpg.setPackageInfo(pc);
        return pc;
    }

    private static void dataSourceConfig(AutoGenerator mpg) {
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/laker?useUnicode=true&useSSL=false&characterEncoding=utf8");
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        mpg.setDataSource(dsc);
    }

    private static String globalConfig(AutoGenerator mpg) {
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        // 生成文件的输出目录
        gc.setOutputDir(projectPath + "/src/main/java");
        // 作者姓名
        gc.setAuthor("laker");
        // 是否打开输出目录
        gc.setOpen(true);
        // 实体属性 Swagger2 注解
        // gc.setSwagger2(true);
        // 是否覆盖已有文件
        gc.setFileOverride(false);
        // 开启 BaseResultMap
        gc.setBaseResultMap(true);
        // 开启 baseColumnList
        gc.setBaseColumnList(true);

        mpg.setGlobalConfig(gc);
        return projectPath;
    }

}

更多详细配置,请参考代码生成器配置一文。

编写配置

MyBatis-Plus 的代码生成器提供了大量的自定义参数供用户选择,能够满足绝大部分人的使用需求。

  • 配置 GlobalConfig

    GlobalConfig globalConfig = new GlobalConfig();
    globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
    globalConfig.setAuthor("jobob");
    globalConfig.setOpen(false);
    
  • 配置 DataSourceConfig

    DataSourceConfig dataSourceConfig = new DataSourceConfig();
    dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/ant?useUnicode=true&useSSL=false&characterEncoding=utf8");
    dataSourceConfig.setDriverName("com.mysql.jdbc.Driver");
    dataSourceConfig.setUsername("root");
    dataSourceConfig.setPassword("password");
    

自定义模板引擎

请继承类 com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine

自定义代码模板

自带内部模板为

//指定自定义模板路径, 位置:/resources/templates/entity2.java.ftl(或者是.vm)
//注意不要带上.ftl(或者是.vm), 会根据使用的模板引擎自动识别
TemplateConfig templateConfig = new TemplateConfig()
    .setEntity("templates/entity2.java");

AutoGenerator mpg = new AutoGenerator();
//配置自定义模板
mpg.setTemplate(templateConfig);

自定义属性注入

InjectionConfig injectionConfig = new InjectionConfig() {
    //自定义属性注入:abc
    //在.ftl(或者是.vm)模板中,通过${cfg.abc}获取属性
    @Override
    public void initMap() {
        Map<String, Object> map = new HashMap<>();
        map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
        this.setMap(map);
    }
};
AutoGenerator mpg = new AutoGenerator();
//配置自定义属性注入
mpg.setCfg(injectionConfig);
entity2.java.ftl
自定义属性注入abc=${cfg.abc}

entity2.java.vm
自定义属性注入abc=$!{cfg.abc}

字段其他信息查询注入

relationship

new DataSourceConfig().setDbQuery(new MySqlQuery() {

    /**
     * 重写父类预留查询自定义字段<br>
     * 这里查询的 SQL 对应父类 tableFieldsSql 的查询字段,默认不能满足你的需求请重写它<br>
     * 模板中调用:  table.fields 获取所有字段信息,
     * 然后循环字段获取 field.customMap 从 MAP 中获取注入字段如下  NULL 或者 PRIVILEGES
     */
    @Override
    public String[] fieldCustom() {
        return new String[]{"NULL", "PRIVILEGES"};
    }
})

实战总结

  • mapper.xml :这里默认的xml生成的位置与mapper在一个目录,不实用,改为diyConfig中 自定义到 resources/mapper下

  • GlobalConfig.setBaseResultMap(true)

        <!-- 通用查询映射结果 -->
        <resultMap id="BaseResultMap" type="com.laker.demo.sys.entity.User">
            <id column="id" property="id" />
            <result column="name" property="name" />
            <result column="age" property="age" />
            <result column="email" property="email" />
        </resultMap>
    
  • GlobalConfig.setBaseColumnList(true)

        <!-- 通用查询结果列 -->
        <sql id="Base_Column_List">
            id, name, age, email
        </sql>
    
  • 添加xxxmapper.xml

    mybatis-plus:
      mapper-locations: classpath*:/mapper/**/*.xml # 默认配置 如果mapper.xml位置是这么放的可以不加
    
  • 自定义controller.java.ftl

    代码

            // 配置模板
            TemplateConfig templateConfig = new TemplateConfig();
            // 配置自定义输出模板
            //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
             templateConfig.setController("templates/controller.java");
    

    模板位置在下图,复制过来改一改。

    package ${package.Controller};
    import org.springframework.web.bind.annotation.RequestMapping;
    <#if restControllerStyle>
    import org.springframework.web.bind.annotation.RestController;
    <#else>
    import org.springframework.stereotype.Controller;
    </#if>
    <#if superControllerClassPackage??>
    import ${superControllerClassPackage};
    </#if>
    
    /**
     * <p>
     * ${table.comment!} 前端控制器
     * </p>
     *
     * @author ${author}
     * @since ${date}
     */
    <#if restControllerStyle>
    @RestController
    <#else>
    @Controller
    </#if>
    @RequestMapping("<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>")
    <#if kotlin>
    class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if>
    <#else>
    <#if superControllerClass??>
    public class ${table.controllerName} extends ${superControllerClass} {
    <#else>
    public class ${table.controllerName} {
    </#if>
    
    }
    </#if>
    
    
  • 规范经验

    • 表命名 resource_highway

      请输入模块名:
      resource
      请输入表名,多个英文逗号分割:
      resource_highway
      
    • 生成的包com.laker.demo.resource

      • controller.HighwayController

常用总结

多表联查

  • 复杂的:直接xml编写吧

  • 简单的:注解编程+关联结果VO

    public interface QuestionMapper extends BaseMapper<Question> {
        // page 翻页对象,可以作为 xml 参数直接使用,传递参数 Page 即自动分页
        @Select("SELECT t_question.*,t_student.`name` FROM t_question,t_student WHERE t_question.student_id=t_student.id")
        List<QuestionStudentVO> getQuestionStudent(Pagination page);
    }
    

开启日志打印

通用

logging:
  level:
    com.xxx.mapper: debug

Mybatis-Plus

这个只能记录在控制台

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

PerformanceInterceptor拦截器,虽然高版本(3.1.0 以上版本)删除了,我们还是可以借鉴下的哈哈。

直接把代码复制到你们本地,使用到的就是下面2个类

步骤一:在MP配置类中配置该插件,并且只适用于DEV环境

// MybatisPlus配置类
@Configuration
public class MyBatisPlusConfig {
    //SQL执行效率插件
    @Bean
    @Profile({"dev"}) // 指定环境为dev生效
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor interceptor = new PerformanceInterceptor();
        // sql美化打印
        interceptor.setFormat(true);
        // 设置SQL超时时间
        interceptor.setMaxTime(5000L);
        // 写入日志
        interceptor.setWriteInLog(true);
        return interceptor;
    }
}

步骤二:设置环境为dev。

spring:
  profiles:
    active: dev

结果如下:

2021-03-09 19:57:10.925  INFO 20232 --- [nio-8080-exec-1] c.a.h.d.common.PerformanceInterceptor    :  Time:15 ms - ID:com.laker.demo.mapper.StakeMapper.insert
Execute SQLINSERT 
    INTO
        resource_stake
        ( road_id, stake_name, state_num, direction, picture_url, lon, lat ) 
    VALUES
        ( 0, 'string', 0, 'string', 'string', 0, 0 )

Mybatis

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

更新和删除

更新和删除默认皆为处理非null字段


写多了CSDN好卡,而且保存老是审核,再开一篇,在《从零搭建开发脚手架 》专栏查找

《从零搭建开发脚手架 Spring Boot集成Mybatis-plus之二》

公众号也会持续输出高质量文章,和大家共同进步。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring BootMyBatis-Plus是两个流行的Java开发框架。Spring Boot是一个用于简化和加速Java应用程序开发的框架,而MyBatis-PlusMyBatis的增强版,提供了更多的特性和功能。 使用Spring Boot2和MyBatis-Plus的组合,能够使开发过程更加高效和简便。Spring Boot2已经集成了很多常用的配置和功能,例如自动配置、快速启动器和监控等。这些功能使得开发者可以更加专注于业务逻辑而不用过多关注繁琐的配置。 而MyBatis-Plus提供了一系列强大且易于使用的功能,例如代码生成器、分页查询、逻辑删除和性能优化等。代码生成器能够帮助开发者快速生成数据库表对应的实体类、Mapper接口以及XML映射文件,大大提高了开发效率。分页查询和逻辑删除功能使得数据操作更加方便和灵活。另外,MyBatis-Plus对SQL语句进行了优化,能够提升数据库查询的性能。 使用Spring Boot2和MyBatis-Plus的组合还能够更好地兼容其他常用的开发工具和框架,例如Spring Security和Swagger等。Spring Security提供了安全认证和授权的功能,能够保护应用程序的安全性。Swagger可以生成API文档,并提供了一个用户友好的UI界面,方便开发者进行接口测试和调试。 总之,Spring Boot2和MyBatis-Plus的组合能够提高开发效率、简化配置、优化性能并提供额外的功能。对于Java开发者来说,这是一个非常不错且受欢迎的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lakernote

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值