x-kq

先创建spring boot项目,不知道怎么创建项目的 可以看我上一篇文章

用到的环境 JDK8 、maven、lombok、mysql 5.7
swagger 是为了方便接口测试

一、Spring boot 集成mybatis plus

mysql数据库准备

建议创建一个新的数据库测试
执行下面初始化SQL:


-- 创建测试用户表
CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT \'主键ID\',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT \'姓名\',
	age INT(11) NULL DEFAULT NULL COMMENT \'年龄\',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT \'邮箱\',
	PRIMARY KEY (id)
);

-- 增加测试数据
INSERT INTO user (id, name, age, email) VALUES
(1, \'Jone\', 18, \'test1@baomidou.com\'),
(2, \'Jack\', 20, \'test2@baomidou.com\'),
(3, \'Tom\', 28, \'test3@baomidou.com\'),
(4, \'Sandy\', 21, \'test4@baomidou.com\'),
(5, \'Billie\', 24, \'test5@baomidou.com\');

1、添加 maven依赖

        <!--mybatis-plus start-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.29</version>
        </dependency>

        <!-- 提供mysql驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <!--mybatis-plus end-->

2、application.yml配置

server:
  port: 9999

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource # 使用druid数据源
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3308/test?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&useSSL=false
    username: root
    password: 999999999

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

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.example.springbootmybatisplus.dao")
@SpringBootApplication
public class SpringbootMybatisPlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootMybatisPlusApplication.class, args);
    }

}

4、编码,写例子测试

4.1、 编写实体类 User.java

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

4.2、 编写Mapper类 UserMapper.java

package com.example.springbootmybatisplus.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.springbootmybatisplus.entity.User;

public interface UserMapper extends BaseMapper<User> {

}

4.3、 编写TestController接口进行测试

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.springbootmybatisplus.dao.UserMapper;
import com.example.springbootmybatisplus.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("testUser")
public class TestController {
    @Autowired
    UserMapper userMapper;

    //直接分页查询
    @RequestMapping(value = "/selectPage",method = RequestMethod.GET)
    public IPage<User> selectPage(){
        log.info("selectPage start");
        IPage<User> page = new Page<>(1,2);
        userMapper.selectPage(page,null);
        if(CollUtil.isNotEmpty(page.getRecords())){
            page.getRecords().forEach(data->{
                log.info("{}",data);
            });
        }
        log.info("selectPage end");
        return page;
    }
    @RequestMapping(value = "/selectById",method = RequestMethod.GET)
    public User selectById(@RequestParam("id")Integer id){
        log.info("selectById start");
        User user = userMapper.selectById(id);
        log.info("user:{}",user);
        log.info("selectById end");
        return user;
    }
}

4.4、 启动项目,接口进行测试
第一步先访问:http://127.0.0.1:9999/testUser/selectById?id=1
第二步再访问接口:http://127.0.0.1:9999/testUser/selectPage

控制台输出


  .   ____          _            __ _ _
 /\\ / ___\'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | \'_ | \'_| | \'_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  \'  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.5.3)

2021-07-27 22:52:25.127  INFO 23542 --- [           main] c.e.s.SpringbootMybatisPlusApplication   : Starting SpringbootMybatisPlusApplication using Java 1.8.0_231 on localhost with PID 23542 (/Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus/target/classes started by xkq in /Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus)
2021-07-27 22:52:25.130  INFO 23542 --- [           main] c.e.s.SpringbootMybatisPlusApplication   : No active profile set, falling back to default profiles: default
2021-07-27 22:52:25.770  WARN 23542 --- [           main] o.m.s.mapper.ClassPathMapperScanner      : No MyBatis mapper was found in \'[com.baomidou.cloud.service.*.mapper*]\' package. Please check your configuration.
2021-07-27 22:52:26.039  INFO 23542 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9999 (http)
2021-07-27 22:52:26.045  INFO 23542 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-07-27 22:52:26.046  INFO 23542 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.50]
2021-07-27 22:52:26.093  INFO 23542 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-07-27 22:52:26.093  INFO 23542 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 918 ms
 _ _   |_  _ _|_. ___ _ |    _ 
| | |\/|_)(_| | |_\  |_)||_|_\ 
     /               |         
                        3.4.1 
2021-07-27 22:52:26.902  INFO 23542 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9999 (http) with context path \'\'
2021-07-27 22:52:26.903  INFO 23542 --- [           main] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed
2021-07-27 22:52:26.913  INFO 23542 --- [           main] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s)
2021-07-27 22:52:26.922  INFO 23542 --- [           main] s.d.s.w.s.ApiListingReferenceScanner     : Scanning for api listing references
2021-07-27 22:52:27.026  INFO 23542 --- [           main] c.e.s.SpringbootMybatisPlusApplication   : Started SpringbootMybatisPlusApplication in 2.274 seconds (JVM running for 2.733)
2021-07-27 22:52:35.289  INFO 23542 --- [nio-9999-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet \'dispatcherServlet\'
2021-07-27 22:52:35.289  INFO 23542 --- [nio-9999-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet \'dispatcherServlet\'
2021-07-27 22:52:35.290  INFO 23542 --- [nio-9999-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2021-07-27 22:52:45.023  INFO 23542 --- [nio-9999-exec-7] c.e.s.controller.TestController          : selectById start
2021-07-27 22:52:45.067  INFO 23542 --- [nio-9999-exec-7] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
2021-07-27 22:52:45.273  INFO 23542 --- [nio-9999-exec-7] c.e.s.controller.TestController          : user:User(id=1, name=Jone, age=18, email=test1@baomidou.com)
2021-07-27 22:52:45.274  INFO 23542 --- [nio-9999-exec-7] c.e.s.controller.TestController          : selectById end
2021-07-27 22:53:38.385  INFO 23542 --- [nio-9999-exec-9] c.e.s.controller.TestController          : selectPage start
2021-07-27 22:53:38.431  INFO 23542 --- [nio-9999-exec-9] c.e.s.controller.TestController          : User(id=1, name=Jone, age=18, email=test1@baomidou.com)
2021-07-27 22:53:38.432  INFO 23542 --- [nio-9999-exec-9] c.e.s.controller.TestController          : User(id=2, name=Jack, age=20, email=test2@baomidou.com)
2021-07-27 22:53:38.432  INFO 23542 --- [nio-9999-exec-9] c.e.s.controller.TestController          : User(id=3, name=Tom, age=28, email=test3@baomidou.com)
2021-07-27 22:53:38.432  INFO 23542 --- [nio-9999-exec-9] c.e.s.controller.TestController          : User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
2021-07-27 22:53:38.432  INFO 23542 --- [nio-9999-exec-9] c.e.s.controller.TestController          : User(id=5, name=Billie, age=24, email=test5@baomidou.com)
2021-07-27 22:53:38.432  INFO 23542 --- [nio-9999-exec-9] c.e.s.controller.TestController          : selectPage end

从日志中可以看到,selectById方法能查询数据,但是分页查询没有生效,后面会说怎么整合分页插件。

上面代码都是参考mybaits plus官方整合h2的例子,然后整合成mysql数据库的,mybaits plus详细文档可以访问官方地址

二、mybatis plus 分页插件

上面的分页没有生效,我们可以输出执行的SQL,看下实际执行的SQL

1、application.yml 配置打印SQL日志

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #配置这个 会把输出执行的SQL

2、访问下面接口,查看日志输出

继续:第一步先访问:http://127.0.0.1:9999/testUser/selectById?id=1
第二步再访问接口:http://127.0.0.1:9999/testUser/selectPage


  .   ____          _            __ _ _
 /\\ / ___\'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | \'_ | \'_| | \'_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  \'  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.5.3)

2021-07-27 22:57:56.973  INFO 26426 --- [           main] c.e.s.SpringbootMybatisPlusApplication   : Starting SpringbootMybatisPlusApplication using Java 1.8.0_231 on localhost with PID 26426 (/Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus/target/classes started by xkq in /Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus)
2021-07-27 22:57:56.976  INFO 26426 --- [           main] c.e.s.SpringbootMybatisPlusApplication   : No active profile set, falling back to default profiles: default
2021-07-27 22:57:57.620  WARN 26426 --- [           main] o.m.s.mapper.ClassPathMapperScanner      : No MyBatis mapper was found in \'[com.baomidou.cloud.service.*.mapper*]\' package. Please check your configuration.
2021-07-27 22:57:57.895  INFO 26426 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9999 (http)
2021-07-27 22:57:57.902  INFO 26426 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-07-27 22:57:57.902  INFO 26426 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.50]
2021-07-27 22:57:57.966  INFO 26426 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-07-27 22:57:57.966  INFO 26426 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 941 ms
Logging initialized using \'class org.apache.ibatis.logging.stdout.StdOutImpl\' adapter.
Parsed mapper file: \'file [/Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus/target/classes/mapper/TestTableMapper.xml]\'
 _ _   |_  _ _|_. ___ _ |    _ 
| | |\/|_)(_| | |_\  |_)||_|_\ 
     /               |         
                        3.4.1 
2021-07-27 22:57:58.826  INFO 26426 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9999 (http) with context path \'\'
2021-07-27 22:57:58.827  INFO 26426 --- [           main] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed
2021-07-27 22:57:58.836  INFO 26426 --- [           main] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s)
2021-07-27 22:57:58.846  INFO 26426 --- [           main] s.d.s.w.s.ApiListingReferenceScanner     : Scanning for api listing references
2021-07-27 22:57:58.968  INFO 26426 --- [           main] c.e.s.SpringbootMybatisPlusApplication   : Started SpringbootMybatisPlusApplication in 2.363 seconds (JVM running for 2.816)
2021-07-27 22:58:04.020  INFO 26426 --- [nio-9999-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet \'dispatcherServlet\'
2021-07-27 22:58:04.020  INFO 26426 --- [nio-9999-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet \'dispatcherServlet\'
2021-07-27 22:58:04.021  INFO 26426 --- [nio-9999-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2021-07-27 22:58:04.044  INFO 26426 --- [nio-9999-exec-1] c.e.s.controller.TestController          : selectById start
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6ca5a623] was not registered for synchronization because synchronization is not active
2021-07-27 22:58:04.087  INFO 26426 --- [nio-9999-exec-1] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
JDBC Connection [com.mysql.jdbc.JDBC4Connection@2a83b478] will not be managed by Spring
==>  Preparing: SELECT id,name,age,email FROM user WHERE id=?
==> Parameters: 1(Integer)
<==    Columns: id, name, age, email
<==        Row: 1, Jone, 18, test1@baomidou.com
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6ca5a623]
2021-07-27 22:58:04.295  INFO 26426 --- [nio-9999-exec-1] c.e.s.controller.TestController          : user:User(id=1, name=Jone, age=18, email=test1@baomidou.com)
2021-07-27 22:58:04.295  INFO 26426 --- [nio-9999-exec-1] c.e.s.controller.TestController          : selectById end
2021-07-27 22:58:09.794  INFO 26426 --- [nio-9999-exec-2] c.e.s.controller.TestController          : selectPage start
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@28b417c9] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.jdbc.JDBC4Connection@2a83b478] will not be managed by Spring
==>  Preparing: SELECT id,name,age,email FROM user
==> Parameters: 
<==    Columns: id, name, age, email
<==        Row: 1, Jone, 18, test1@baomidou.com
<==        Row: 2, Jack, 20, test2@baomidou.com
<==        Row: 3, Tom, 28, test3@baomidou.com
<==        Row: 4, Sandy, 21, test4@baomidou.com
<==        Row: 5, Billie, 24, test5@baomidou.com
<==      Total: 5
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@28b417c9]
2021-07-27 22:58:09.818  INFO 26426 --- [nio-9999-exec-2] c.e.s.controller.TestController          : User(id=1, name=Jone, age=18, email=test1@baomidou.com)
2021-07-27 22:58:09.818  INFO 26426 --- [nio-9999-exec-2] c.e.s.controller.TestController          : User(id=2, name=Jack, age=20, email=test2@baomidou.com)
2021-07-27 22:58:09.818  INFO 26426 --- [nio-9999-exec-2] c.e.s.controller.TestController          : User(id=3, name=Tom, age=28, email=test3@baomidou.com)
2021-07-27 22:58:09.818  INFO 26426 --- [nio-9999-exec-2] c.e.s.controller.TestController          : User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
2021-07-27 22:58:09.818  INFO 26426 --- [nio-9999-exec-2] c.e.s.controller.TestController          : User(id=5, name=Billie, age=24, email=test5@baomidou.com)
2021-07-27 22:58:09.818  INFO 26426 --- [nio-9999-exec-2] c.e.s.controller.TestController          : selectPage end

从执行SQL的日志看到selectById方法没问题,主要是selectPage方法没有加limit分页

3、配置mybatis plus分页插件,添加MybatisPlusConfig.java

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//Spring boot方式
@Configuration
public class MybatisPlusConfig {

//    // 旧版
//    @Bean
//    public PaginationInterceptor paginationInterceptor() {
//        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
//        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
//        // paginationInterceptor.setOverflow(false);
//        // 设置最大单页限制数量,默认 500 条,-1 不受限制
//        // paginationInterceptor.setLimit(500);
//        // 开启 count 的 join 优化,只针对部分 left join
//        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
//        return paginationInterceptor;
//    }

    // 最新版
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

}

4、测试MybatisPlusInterceptor分页插件

加完MybatisPlusConfig后重启服务,访问接口: http://127.0.0.1:9999/testUser/selectPage
从SQL执行日志可以看出 先执行COUNT查询总条数,最后在LIMIT分页取数据,说明分页插件配置成功了

2021-07-27 23:02:40.225  INFO 28656 --- [nio-9999-exec-2] c.e.s.controller.TestController          : selectPage start
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6acc6ecd] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.jdbc.JDBC4Connection@2320cee0] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) FROM user
==> Parameters: 
<==    Columns: COUNT(*)
<==        Row: 5
<==      Total: 1
==>  Preparing: SELECT id,name,age,email FROM user LIMIT ?
==> Parameters: 2(Long)
<==    Columns: id, name, age, email
<==        Row: 1, Jone, 18, test1@baomidou.com
<==        Row: 2, Jack, 20, test2@baomidou.com
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6acc6ecd]
2021-07-27 23:02:40.299  INFO 28656 --- [nio-9999-exec-2] c.e.s.controller.TestController          : User(id=1, name=Jone, age=18, email=test1@baomidou.com)
2021-07-27 23:02:40.299  INFO 28656 --- [nio-9999-exec-2] c.e.s.controller.TestController          : User(id=2, name=Jack, age=20, email=test2@baomidou.com)
2021-07-27 23:02:40.299  INFO 28656 --- [nio-9999-exec-2] c.e.s.controller.TestController          : selectPage end

三、 mybatis plus 代码生成器

我对 mybatis plus 代码生成器的需求就是:
1、生成的代码 需要支持单表的crud
2、代码生成器通常默认生成的文件是controller、service、servieImpl、mapper(dao)、xml、entity;但是我还想多生成一个Vo类(多生成一个vo,主要是为了后期业务熟练了,想对已有的模版 进行修改 或者 增加生成新的生成文件,可以做一个参考)
3、xml文件 我要生成到 /src/main/resources/mapper文件夹下面

1、这是代码生成器需要生成的表,及测试数据

-- 创建表
CREATE TABLE `test_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL COMMENT \'名称\',
  `start_date` date DEFAULT NULL COMMENT \'开始日期\',
  `create_time` datetime DEFAULT NULL COMMENT \'创建时间\',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT=\'测试-表\';

-- 创建一条测试数据
INSERT INTO `test_table` VALUES (1, \'你好\', \'2021-07-27\', \'2021-07-27 23:10:02\');

2、Vo类模版文件

路径及文件名是:/my_template/my_entity_vo.java.ftl
把mybatis-plus-generator.jar包的entity模版文件复制出来,模版内容稍微改了下类名和package,实际生成的文件跟entity差不多
下图就是我复制模版的位置,因为我选择的是freemarker 模版,就复制了后缀是ftl的文件
image

最终my_entity_vo.java.ftl模版内容如下:

package com.example.springbootmybatisplus.vo;

<#list table.importPackages as pkg>
import ${pkg};
</#list>
<#if swagger2>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Data;
import lombok.EqualsAndHashCode;
    <#if chainModel>
import lombok.experimental.Accessors;
    </#if>
</#if>

/**
 * <p>
 * ${table.comment!}
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */
<#if entityLombokModel>
@Data
    <#if superEntityClass??>
@EqualsAndHashCode(callSuper = true)
    <#else>
@EqualsAndHashCode(callSuper = false)
    </#if>
    <#if chainModel>
@Accessors(chain = true)
    </#if>
</#if>
<#if table.convert>
@TableName("${table.name}")
</#if>
<#if swagger2>
@ApiModel(value="${entity}对象", description="${table.comment!}")
</#if>
<#if superEntityClass??>
public class ${entity}Vo extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
<#elseif activeRecord>
public class ${entity}Vo extends Model<${entity}> {
<#else>
public class ${entity}Vo implements Serializable {
</#if>

<#if entitySerialVersionUID>
    private static final long serialVersionUID = 1L;
</#if>
<#-- ----------  BEGIN 字段循环遍历  ---------->
<#list table.fields as field>
    <#if field.keyFlag>
        <#assign keyPropertyName="${field.propertyName}"/>
    </#if>

    <#if field.comment!?length gt 0>
        <#if swagger2>
    @ApiModelProperty(value = "${field.comment}")
        <#else>
    /**
     * ${field.comment}
     */
        </#if>
    </#if>
    <#if field.keyFlag>
        <#-- 主键 -->
        <#if field.keyIdentityFlag>
    @TableId(value = "${field.annotationColumnName}", type = IdType.AUTO)
        <#elseif idType??>
    @TableId(value = "${field.annotationColumnName}", type = IdType.${idType})
        <#elseif field.convert>
    @TableId("${field.annotationColumnName}")
        </#if>
        <#-- 普通字段 -->
    <#elseif field.fill??>
    <#-- -----   存在字段填充设置   ----->
        <#if field.convert>
    @TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill})
        <#else>
    @TableField(fill = FieldFill.${field.fill})
        </#if>
    <#elseif field.convert>
    @TableField("${field.annotationColumnName}")
    </#if>
    <#-- 乐观锁注解 -->
    <#if (versionFieldName!"") == field.name>
    @Version
    </#if>
    <#-- 逻辑删除注解 -->
    <#if (logicDeleteFieldName!"") == field.name>
    @TableLogic
    </#if>
    private ${field.propertyType} ${field.propertyName};
</#list>
<#------------  END 字段循环遍历  ---------->

<#if !entityLombokModel>
    <#list table.fields as field>
        <#if field.propertyType == "boolean">
            <#assign getprefix="is"/>
        <#else>
            <#assign getprefix="get"/>
        </#if>
    public ${field.propertyType} ${getprefix}${field.capitalName}() {
        return ${field.propertyName};
    }

    <#if chainModel>
    public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
    <#else>
    public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
    </#if>
        this.${field.propertyName} = ${field.propertyName};
        <#if chainModel>
        return this;
        </#if>
    }
    </#list>
</#if>

<#if entityColumnConstant>
    <#list table.fields as field>
    public static final String ${field.name?upper_case} = "${field.name}";

    </#list>
</#if>
<#if activeRecord>
    @Override
    protected Serializable pkVal() {
    <#if keyPropertyName??>
        return this.${keyPropertyName};
    <#else>
        return null;
    </#if>
    }

</#if>
<#if !entityLombokModel>
    @Override
    public String toString() {
        return "${entity}{" +
    <#list table.fields as field>
        <#if field_index==0>
            "${field.propertyName}=" + ${field.propertyName} +
        <#else>
            ", ${field.propertyName}=" + ${field.propertyName} +
        </#if>
    </#list>
        "}";
    }
</#if>
}

3、添加maven依赖

我选择使用freemarker作为模版引擎,所以需要引入freemarker依赖

        <!--mybatis-plus 代码生成器 start-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>
        <!--mybatis-plus 代码生成器 end-->

4、配置文件添加扫描xml位置以及实体类的位置

这个主要是为了让mapper(dao)跟xml文件里面的方法关联起来

mybatis-plus:
  #xml文件路径,多个路径有xml文件用逗号分隔
  mapper-locations: classpath*:/mapper/**/*.xml
  #实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.example.springbootmybatisplus.entity

5、代码生成器启动类

import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
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 java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

// 演示例子,执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
@Slf4j
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();
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        log.info("projectPath:{}",projectPath);

        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("小旋风");//开发人员
        gc.setOpen(false);//代码生成后,是否打开文件夹
        gc.setSwagger2(true);// 实体属性 Swagger2 注解
        gc.setFileOverride(false);//是否覆盖已有文件(true会覆盖 已经存在的文件)
        /**
         * 只使用 java.util.date 代替
         */
        gc.setDateType(DateType.ONLY_DATE);

        gc.setBaseColumnList(true);//开启 baseColumnList
        gc.setBaseResultMap(true);//开启 BaseResultMap

        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://127.0.0.1:3308/test?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&useSSL=false");
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("999999999");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
//        pc.setModuleName(scanner("模块名"));
        pc.setParent("com.example.springbootmybatisplus");
        pc.setMapper("dao");//生产的mapper 放到dao目录下


        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        // 如果模板引擎是 freemarker
        String templatePath = "/my_template/my_entity_req.java.ftl";//多生成一个实体类,仅仅做参考,没有这个需求的,可以去掉
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        String templatePathXml = "/templates/mapper.xml.ftl";//下面templateConfig.setXml(null); 自定义生成xml,默认的xml设置为null

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePathXml) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                return projectPath + "/src/main/resources/mapper/"
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });


        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                return projectPath + "/src/main/java/com/example/springbootmybatisplus/vo/" +tableInfo.getEntityName() + "Vo" + StringPool.DOT_JAVA;
            }
        });
        /*
        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);

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

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

        /**
         * 设置不生成 默认的xml,因为生成的位置会在 java文件夹下面,
         * 我想生成的xml放到resources.mapper文件夹下面,
         * 所以使用设置了自定义【templatePathXml】的模版去生成
         */
        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//        strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        // 公共父类
//        strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
        // 写于父类中的公共字段
//        strategy.setSuperEntityColumns("id"); //没有父类公共字段的去掉
        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix(pc.getModuleName() + "_");

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

5、运行CodeGenerator类的main方法

在控制台输入要生成的表名【test_table】,下面是输出日志:

23:43:45.919 [main] INFO com.example.springbootmybatisplus.generator.CodeGenerator - projectPath:/Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus
请输入表名,多个英文逗号分割:
test_table
23:43:55.961 [main] DEBUG com.baomidou.mybatisplus.generator.AutoGenerator - ==========================准备生成文件...==========================
23:43:56.555 [main] DEBUG com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine - 模板:/templates/mapper.xml.ftl;  文件:/Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus/src/main/resources/mapper//TestTableMapper.xml
23:43:56.641 [main] DEBUG com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine - 模板:/templates/entity.java.ftl;  文件:/Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus/src/main/java/com/example/springbootmybatisplus/entity/TestTable.java
23:43:56.643 [main] DEBUG com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine - 模板:/templates/mapper.java.ftl;  文件:/Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus/src/main/java/com/example/springbootmybatisplus/dao/TestTableMapper.java
23:43:56.645 [main] DEBUG com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine - 模板:/templates/service.java.ftl;  文件:/Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus/src/main/java/com/example/springbootmybatisplus/service/ITestTableService.java
23:43:56.646 [main] DEBUG com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine - 模板:/templates/serviceImpl.java.ftl;  文件:/Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus/src/main/java/com/example/springbootmybatisplus/service/impl/TestTableServiceImpl.java
23:43:56.648 [main] DEBUG com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine - 模板:/templates/controller.java.ftl;  文件:/Users/xkq/Downloads/it/xkq_git项目/springboot-example/springboot-mybatis-plus/src/main/java/com/example/springbootmybatisplus/controller/TestTableController.java
23:43:56.648 [main] DEBUG com.baomidou.mybatisplus.generator.AutoGenerator - ==========================文件生成完成!!!==========================

6、最终生成的效果图如下

image

7、测试生成的代码

写个查询方法,来测试一下

7.1、TestTableMapper.xml 添加getCustomOne方法

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springbootmybatisplus.dao.TestTableMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.example.springbootmybatisplus.entity.TestTable">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="start_date" property="startDate" />
        <result column="create_time" property="createTime" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, name, start_date, create_time
    </sql>

    <select id="getCustomOne" resultMap="BaseResultMap" >
        select id, name, start_date, create_time from test_table limit 1
    </select>
</mapper>

7.2、TestTableMapper.java 添加getCustomOne方法

import com.example.springbootmybatisplus.entity.TestTable;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * <p>
 * 测试-表 Mapper 接口
 * </p>
 *
 * @author 小旋风
 * @since 2021-07-27
 */
public interface TestTableMapper extends BaseMapper<TestTable> {
    public TestTable getCustomOne();
}

7.3、编写接口进行测试

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.springbootmybatisplus.dao.TestTableMapper;
import com.example.springbootmybatisplus.entity.TestTable;
import com.example.springbootmybatisplus.service.ITestTableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 * 测试-表 前端控制器
 * </p>
 *
 * @author 小旋风
 * @since 2021-07-27
 */
@RestController
@RequestMapping("/test-table")
public class TestTableController {

        @Autowired
    private ITestTableService testTableService;

    @Autowired
    private TestTableMapper testTableMapper;

    @RequestMapping(value = "/getCustomOne",method = RequestMethod.GET)
    public TestTable getCustomOne(){
        //这个方法主要是验证 mapper跟xml文件 关联上了,mapper-locations生效了
        return testTableMapper.getCustomOne();
    }

    @RequestMapping(value = "/page",method = RequestMethod.GET)
    public IPage<TestTable> page(){
        Page<TestTable> page = new Page();
        page.setSize(10);
        return testTableService.page(page);
    }
}

7.4、访问接口

访问接口:http://127.0.0.1:9999/test-table/getCustomOne
日志输出如下:

Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@262025d3] was not registered for synchronization because synchronization is not active
2021-07-27 23:53:18.981  INFO 55251 --- [nio-9999-exec-1] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
JDBC Connection [com.mysql.jdbc.JDBC4Connection@30c4c95c] will not be managed by Spring
==>  Preparing: select id, name, start_date, create_time from test_table limit 1
==> Parameters: 
<==    Columns: id, name, start_date, create_time
<==        Row: 1, 你好, 2021-07-27, 2021-07-27 23:10:02.0
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@262025d3]

image
日志输出无报错,浏览器上也看到返回结果了,说明代码生成器整合成功了~

三、集成swaager

上面的例子,不放整合swagger的代码了,毕竟spring boot整合mybaits plus需要配置的东西不多,放在一起有点乱,就单独拎出来写,集成swagger 是为了方便测试接口用。

1、pom.xml添加依赖:

        <!--测试接口 添加swagger start-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.6.1</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.6.1</version>
        </dependency>
        <!--测试接口 添加swagger end-->

2、配置SwaggerConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;


@Configuration
@EnableSwagger2
public class SwaggerConfig {

    private Boolean swaggerEnabled = true;//是否启用swagger 可以把配置放到配置文件

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .enable(swaggerEnabled)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.springbootmybatisplus"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("接口文档")
                .description("spring boot整合mybatis plus~")
                .termsOfServiceUrl("https://www.cnblogs.com/x-kq/p/15068023.html")
                .version("6.6.6")
                .build();
    }
}

3、swagger访问地址

访问这个地址测试接口比较方便
http://127.0.0.1:9999/swagger-ui.html


代码我已经传到gitee了,有兴趣的可以clone,传送门


分类:

技术点:

相关文章: