SpringBoot3 + MyBatisPlus 快速整合

一、前言

MyBatis 最佳搭档,只做增强不做改变,为简化开发、提高效率而生。 这个发展到目前阶段已经很成熟了,社区也比较活跃,可以放心使用。官网地址:https://baomidou.com

二、快速开始

引入依赖

这里我引入了核心 starter 依赖,以及官方提供的代码生成器依赖,如果你不用代码生成器可以不引用

xml 复制代码
<properties>
  <mybatis-plus.version>3.5.7</mybatis-plus.version> <!-- mybatis增强 orm 框架 -->
</properties>

<dependencies>
  <!--   mybatis-plus 相关依赖   -->
  <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
      <version>${mybatis-plus.version}</version>
  </dependency>
  <!-- 代码生成器 -->
  <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-generator</artifactId>
      <version>${mybatis-plus.version}</version>
  </dependency>
  <!--  mysql 依赖 版本由继承的 spring-boot-starter-parent 控制,也可以自己指定  -->
  <dependency>
      <groupId>com.mysql</groupId>
      <artifactId>mysql-connector-j</artifactId>
  </dependency>
</dependencies>

配置数据库连接

yaml 复制代码
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/itshare-dev?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&rewriteBatchedStatements=true
    username: root
    password: root

这样整合就完成了,接下来就可以编写我们的业务代码了。

三、业务开发

使用 mybatis-plus 的基本开发流程一般是这样的,他和一些全自动的 ORM 框架还是有点区别的,比如 SpringDataJPA 或者 Hibernate 并不能根据实体对象自动执行 ddl 创建表结构(现在可以通过插件做到,这里我们不深究),一般都是通过先有表,再有实体对象

通常是:

创建数据表 -> 代码生成器生成基础类 -> 在这个基础上开发业务代码

当然你可以在代码生成器阶段尽可能的抽象出相似的地方,甚至可以生成简单的 CRUD 代码,市面上有很多案例可供参考,若依,eladmin 等等。这里我只介绍基础的 entity、mapper、service 生成。

3.1 创建数据表

这里我就不列举了,根据你自己业务来。

3.2 代码生成器

引入依赖

xml 复制代码
<!-- 代码生成器 -->
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-generator</artifactId>
  <version>${mybatis-plus.version}</version>
</dependency>
<!-- 模板引擎 -->
<dependency>
  <groupId>org.freemarker</groupId>
  <artifactId>freemarker</artifactId>
</dependency>

代码生成工具类

java 复制代码
public class CodeGenerator {


    private static final String DB_URL = "jdbc:mysql://localhost:3306/itshare-dev?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&tinyInt1isBit=false";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "root";

    public static void main(String[] args) {

        AtomicReference<String> loadModulePackageName = new AtomicReference<>("");
        // 获取当前路径
        String path = System.getProperty("user.dir");
        // &tinyInt1isBit=false
        FastAutoGenerator.create(DB_URL, USERNAME, PASSWORD)
        .globalConfig((scanner, builder) -> {
            // 设置作者
            builder.author("曹申阳")
            .disableOpenDir()
            .enableSpringdoc() // 如果想用swagger,生成 springdoc 规范注解 把这个放开
            // 指定输出目录
            .outputDir(path + "\\src\\test\\java");
        })
        .dataSourceConfig(builder ->
                          builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                              if (JdbcType.TINYINT == metaInfo.getJdbcType()) {
                                  return DbColumnType.INTEGER;
                              }
                              return typeRegistry.getColumnType(metaInfo);
                          })
                         )
        .packageConfig((scanner, builder) -> {
            loadModulePackageName.set(scanner.apply("请输入当前父包模块名称:"));
            builder.parent("com.yang.itshare") // 设置父包名
            .moduleName(loadModulePackageName.get()) // 设置父包模块名
            .service("service")
            .serviceImpl("service.impl")
            .mapper("mapper")
            .controller("controller")
            .entity("entity")
            // 设置mapperXml生成路径
            .pathInfo(Collections.singletonMap(OutputFile.xml, path + "\\src\\main\\resources\\mapper\\" + loadModulePackageName.get()));
        })
        .strategyConfig((scanner, builder) -> {
            // 设置需要生成的表名
            builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
            .addTablePrefix("itshare_") // 设置过滤表前缀
            .entityBuilder() // 设置 entity 生成规则
            .addTableFills(new Column("create_time", FieldFill.INSERT))
            .addTableFills(new Column("update_time", FieldFill.INSERT_UPDATE))
            .logicDeleteColumnName("is_deleted")
            .idType(IdType.AUTO)
            .enableLombok()// lombok 注解
            .controllerBuilder() // 设置 controller 生成规则
            .enableRestStyle() // 开启生成@RestController 控制器
            .build();
        }
                       )
        .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
        .execute();
    }

    /**
     * 处理 all 情况
     */
    protected static List<String> getTables(String tables) {
        return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
    }

}

亲测可用,注释也很清楚,想要自己配置可以参考配置文件 https://baomidou.com/reference/new-code-generator-configuration/

运行测试一下:我习惯将生成的放在 test 下,然后再复制到项目下,方便调试,如果你足够自信,可以指定到想要的地方,一步到位。

这个时候还差最后一步,开启 mapper 扫描,就可以正常使用了

java 复制代码
@MapperScan("com.yang.itshare.*.mapper")

你可以加在启动类上,或者其它可以被扫描到的类上,我习惯加载 mybatis 的插件配置类上,后面会介绍。

四、常用插件功能

4.1 逻辑删除

配置全局逻辑删除属性

yaml 复制代码
mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: is_deleted # 全局逻辑删除字段名
      logic-delete-value: 1 # 逻辑已删除值
      logic-not-delete-value: 0 # 逻辑未删除值
  # 打印 sql 日志
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  # 配置mapper的扫描,找到所有的mapper.xml映射文件 如果和默认路径一样可以不配置
  mapper-locations: classpath*:/mapper/**/*.xml

这里我把常用的也放出来了,日志打印,以及 xml 扫描,我一般就放默认地址,这里不加也可以,防止大家想要修改位置,可以在这里配置路径。

加逻辑删除注解

如果你使用的是我上面的代码生成器代码,会自动添加注解

否则,需要自己完成这一步。

之后在调用 mybatis-plus 封装的查询以及删除操作时,会默认加上这个删除的判断,比如查询会过滤掉以删除的,删除会变成修改这个删除标记的状态值,并不会真正的删除。注意,如果是使用自己编写的 xml 将不会生效。

4.2 自动填充字段

实现 MetaObjectHandler

java 复制代码
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

@Override
public void insertFill(MetaObject metaObject) {
    log.info("start insert fill ....");
    this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
    this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}

@Override
public void updateFill(MetaObject metaObject) {
    log.info("start update fill ....");
    this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}

实体类上添加注解

如果你使用我上面的代码生成器,会自动添加,否则要自己指定

4.3 分页插件和防止全表更新与删除插件

创建配置类

java 复制代码
@Configuration
@MapperScan("com.yang.itshare.*.mapper")
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); // 防全表更新与删除插件
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInnerInterceptor.setMaxLimit(1000L);
        interceptor.addInnerInterceptor(paginationInnerInterceptor); // 如果配置多个插件, 切记分页最后添加
        return interceptor;
    }
}

我一般会在这里加上 mapper 的扫描,当然你也可以加在启动类上

还有很多可用插件,大家根据需要引入即可 https://baomidou.com/plugins/

五、总结

这样我们完成了基本的整合,已经可以满足我们前期的开发工作。至于一些高级功能,比如 多数据源支持,数据权限插件,等等。等我们需要的时候,可以自己查阅官方文档进行添加,官方文档写的很详细。

相关推荐
Yhame.25 分钟前
Java 集合框架中的 List、ArrayList 和 泛型 实例
java
coding侠客26 分钟前
Spring Boot 多数据源解决方案:dynamic-datasource-spring-boot-starter 的奥秘
java·spring boot·后端
委婉待续31 分钟前
java抽奖系统(八)
java·开发语言·状态模式
weixin_537590451 小时前
《Java编程入门官方教程》第八章练习答案
java·开发语言·servlet
CodeClimb2 小时前
【华为OD-E卷-最左侧冗余覆盖子串 100分(python、java、c++、js、c)】
java·python·华为od
武昌库里写JAVA2 小时前
使用React Strict DOM改善React生态系统
数据结构·vue.js·spring boot·算法·课程设计
嗨小陈2 小时前
旅游推荐系统设计与实现 计算机毕业设计 有源码 P10090
spring boot·课程设计·旅游·计算机毕业设计
Q_19284999062 小时前
基于Spring Boot的大学就业信息管理系统
java·spring boot·后端
xmh-sxh-13142 小时前
常用数据库类型介绍
java