NyBatis-plus是一个 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性:
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
快速入门
1. 添加依赖
首先,你需要在你的 pom.xml
文件中添加 MyBatis-Plus 的相关依赖。同时,由于 MyBatis-Plus 依赖于 MyBatis,因此你也需要添加 MyBatis 的依赖(但通常 MyBatis-Plus 的 starter 会自动包含 MyBatis 的依赖)。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.7</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>你的MySQL驱动版本</version>
</dependency>
2. 配置数据库连接
在 application.properties
或 application.yml
文件中配置数据库连接信息。
application.properties 示例:
spring.datasource.url=jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# MyBatis-Plus 配置
mybatis-plus.mapper-locations=classpath:/mapper/**/*.xml
mybatis-plus.type-aliases-package=com.yourpackage.entity
mybatis-plus.global-config.db-config.id-type=auto
# 开启 MyBatis-Plus 的日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
application.yml 示例:
spring:
datasource:
url: jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: root
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
type-aliases-package: com.yourpackage.entity
global-config:
db-config:
id-type: auto
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3. 配置 MyBatis-Plus 分页插件
如果你打算使用 MyBatis-Plus 的分页功能,你还需要在 Spring Boot 的配置类中配置分页插件。
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
4. 编写 Mapper 接口和 XML 文件
根据你的数据库表,编写相应的 Mapper 接口和 Mapper XML 文件。MyBatis-Plus 支持注解和 XML 两种方式进行 SQL 映射。
5. 使用 MyBatis-Plus
在你的 Service 层或 Controller 层中,通过注入 Mapper 接口来使用 MyBatis-Plus 提供的各种便捷功能。
条件构造器
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
条件构造器主要包括以下几种类型,它们分别用于不同类型的 SQL 操作:
- QueryWrapper:用于构造查询条件,继承自 AbstractWrapper。
- UpdateWrapper:用于构造更新条件,继承自 AbstractWrapper。
- LambdaQueryWrapper:基于 Lambda 表达式的查询条件构造器,用于避免硬编码列名,提高代码的可读性和可维护性。
- LambdaUpdateWrapper:基于 Lambda 表达式的更新条件构造器,同样用于避免硬编码列名。
//QueryWrapper
// 构造查询条件
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John") // 等于 =
.like("email", "test@example.com") // 模糊查询 LIKE
.gt("age", 18) // 大于 >
.orderByAsc("create_time"); // 排序
// 在 Mapper 接口中使用
List<User> users = userMapper.selectList(queryWrapper);
//LambdaQueryWrapper
// 使用 Lambda 表达式构造查询条件,避免硬编码列名
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getName, "John") // 等于 =
.like(User::getEmail, "test@example.com") // 模糊查询 LIKE
.gt(User::getAge, 18) // 大于 >
.orderByAsc(User::getCreateTime); // 排序
// 在 Mapper 接口中使用
List<User> users = userMapper.selectList(lambdaQueryWrapper);
条件构造器提供了丰富的方法来构建各种 SQL 条件,包括但不限于:
eq
:等于 =ne
:不等于 <>gt
:大于 >ge
:大于等于 >=lt
:小于 <le
:小于等于 <=like
:模糊查询 LIKEnotLike
:模犊查询 NOT LIKEin
:字段 IN 查询notIn
:字段 NOT IN 查询isNull
:字段 IS NULLisNotNull
:字段 IS NOT NULLgroupBy
:分组 GROUP BYhaving
:HAVING 条件orderByAsc
:升序排序orderByDesc
:降序排序orderBy
:自定义排序
// 设置所有字段的相等条件,如果字段值为null,则根据null2IsNull参数决定是否设置为IS NULL
allEq(Map<String, Object> params)
allEq(Map<String, Object> params, boolean null2IsNull)
allEq(boolean condition, Map<String, Object> params, boolean null2IsNull)
// 设置所有字段的相等条件,通过filter过滤器决定哪些字段应该被包含,如果字段值为null,则根据null2IsNull参数决定是否设置为IS NULL
allEq(BiPredicate<String, Object> filter, Map<String, Object> params)
allEq(BiPredicate<String, Object> filter, Map<String, Object> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<String, Object> filter, Map<String, Object> params, boolean null2IsNull)
流式查询
实现流式查询的方法
1. 使用游标(Cursor)
虽然 MyBatis-Plus 没有内置游标支持,但你可以通过原生的 JDBC 来实现。在 JDBC 中,你可以设置 Statement
对象的 fetchSize
属性为 Integer.MIN_VALUE
或其他小的值,这告诉 JDBC 驱动程序使用流式检索(如果数据库和 JDBC 驱动程序支持)。然而,这种方法需要你直接使用 JDBC API,并可能需要手动处理一些 MyBatis-Plus 封装好的功能。
2. 分页查询
虽然不是真正的流式查询,但分页查询可以作为一种处理大量数据的替代方案。通过配置合适的分页参数(如每页数量),你可以分批次地获取和处理数据,从而避免一次性加载所有数据到内存中。MyBatis-Plus 提供了方便的分页插件(PaginationInterceptor
),可以很容易地实现分页查询。
3. 自定义 ResultHandler
在 MyBatis 中(MyBatis-Plus 继承自 MyBatis),你可以通过自定义 ResultHandler
来处理查询结果。ResultHandler
允许你在处理每行结果时直接进行操作,而不是将结果集一次性加载到内存中。这种方法更接近流式处理的思想,但需要更多的编码工作。
// 结合分页,按批次从数据库拉取数据出来跑批,例如从数据库获取10万记录,做数据处理
Page<H2User> page = new Page<>(1, 100000);
baseMapper.selectList(page, Wrappers.emptyWrapper(), new ResultHandler<H2User>() {
int count = 0;
@Override
public void handleResult(ResultContext<? extends H2User> resultContext) {
H2User h2User = resultContext.getResultObject();
System.out.println("当前处理第" + (++count) + "条记录: " + h2User);
// 在这里进行你的业务处理,比如分发任务
}
});
// 从数据库获取表所有记录,做数据处理
baseMapper.selectList(Wrappers.emptyWrapper(), new ResultHandler<H2User>() {
int count = 0;
@Override
public void handleResult(ResultContext<? extends H2User> resultContext) {
H2User h2User = resultContext.getResultObject();
System.out.println("当前处理第" + (++count) + "条记录: " + h2User);
// 在这里进行你的业务处理,比如分发任务
}
});
@Autowired
private SomeMapper someMapper;
public void streamProcessResults() {
someMapper.selectSomeData(new ResultHandler<SomeEntity>() {
@Override
public void handleResult(ResultContext<? extends SomeEntity> context) {
SomeEntity entity = context.getResult();
// 处理每一行数据
System.out.println(entity.toString());
// 注意:不需要手动关闭资源或移动结果集,MyBatis 会处理这些
}
});
}
// Mapper 接口
public interface SomeMapper {
void selectSomeData(ResultHandler<SomeEntity> handler);
}
// Mapper XML 文件
<select id="selectSomeData" resultType="SomeEntity">
SELECT * FROM some_table
</select>