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