是否厌倦了手写SQL的繁琐?MyBatis-Plus让数据库操作像呼吸一样简单! 本文带你零基础掌握这个提升开发效率300%的神器~
MyBatis-Plus(简称MP)是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。它就像给MyBatis装上了涡轮增压引擎,让你的数据库操作飞起来!
设计理念:成为MyBatis最好的搭档,如同魂斗罗中的1P和2P,合作无间效率翻倍。
传统MyBatis痛点 | MyBatis-Plus解决方案 |
---|---|
每个表都要写CRUD方法 | 内置通用Mapper自动实现 |
动态SQL拼接复杂 | 链式条件构造器直观构建 |
分页逻辑重复编写 | 内置分页插件一键搞定 |
字段映射配置繁琐 | 智能注解自动映射 |
基础代码编写耗时长 | 代码生成器秒出基础代码 |
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.3.1version>
dependency>
BaseMapper接口提供开箱即用的方法:
public interface UserMapper extends BaseMapper<User> {
// 无需写任何方法!已有20+基础方法
}
// 使用示例
List<User> users = userMapper.selectList(null); // 查询全部
userMapper.insert(newUser); // 插入
userMapper.deleteById(1); // 按ID删除
告别SQL拼接!链式调用构建复杂查询:
// 查询年龄>18且名字包含“张”的用户,按年龄降序
List<User> users = userMapper.selectList(
Wrappers.<User>query()
.select("id", "name", "age") // 指定字段
.gt("age", 18)
.like("name", "张")
.orderByDesc("age")
);
// 等效SQL:SELECT id,name,age FROM user WHERE age > 18 AND name LIKE '%张%' ORDER BY age DESC
编译级安全查询(防字段拼写错误):
// 传统方式(易错)
queryWrapper.eq("user_name", "张三");
// Lambda方式(IDE自动提示)
LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
wrapper.eq(User::getName, "张三") // 编译期检查字段
.between(User::getAge, 18, 30);
4种主键生成策略自由选择:
@Data
public class User {
@TableId(type = IdType.ASSIGN_ID) // 雪花算法生成分布式ID
private Long id;
@TableId(type = IdType.AUTO) // 数据库自增ID
private Integer userId;
}
支持策略:
AUTO
:数据库自增ASSIGN_ID
:雪花算法(分布式)ASSIGN_UUID
:UUIDINPUT
:手动输入插件名称 | 功能 | 启用配置 |
---|---|---|
分页插件 | 自动分页处理 | @Bean PaginationInterceptor |
乐观锁插件 | 数据版本控制防冲突 | @Bean OptimisticLockerInterceptor |
性能分析插件 | 输出SQL及执行时间 | @Bean PerformanceInterceptor |
防止全表操作插件 | 阻断危险的delete/update操作 | 默认启用 |
一键生成全套CRUD代码:
// 配置生成规则
AutoGenerator generator = new AutoGenerator();
generator.setGlobalConfig(config); // 全局配置
generator.setDataSource(dsConfig); // 数据源
generator.setPackageInfo(pkgConfig); // 包配置
generator.setStrategy(strategyConfig); // 策略
generator.execute(); // 执行生成
生成内容:
功能 | MyBatis | MyBatis-Plus | 优势点 |
---|---|---|---|
CRUD实现 | 需手动编写SQL | 内置通用CRUD方法 | 减少80%代码量 |
条件构造 | XML动态SQL标签 | 链式API/Lambda表达式 | 编码效率提升50%+ |
分页支持 | 需第三方插件 | 内置物理分页插件 | 一键分页 |
代码生成 | 无 | 内置代码生成器 | 秒出基础代码 |
主键策略 | 需手动处理 | 4种主键策略注解支持 | 分布式ID轻松实现 |
字段映射 | 需resultMap配置 | @TableField 智能映射 |
自动转换驼峰下划线 |
SQL安全 | 需自行防注入 | 内置SQL注入剥离器 | 安全无忧 |
实现相同功能(用户分页查询):
// === MyBatis传统方式 ===
// 1. UserMapper.xml中写SQL
<select id="selectByPage" resultType="User">
SELECT * FROM user
WHERE name LIKE #{name}
LIMIT #{offset}, #{limit}
</select>
// 2. Mapper接口声明方法
List<User> selectByPage(@Param("name") String name,
@Param("offset") int offset,
@Param("limit") int limit);
// 3. 手动计算分页参数
int offset = (pageNum - 1) * pageSize;
// === MyBatis-Plus方式 ===
Page<User> page = new Page<>(pageNum, pageSize);
userMapper.selectPage(page, Wrappers.<User>query()
.like("name", name));
结论:MP减少12行代码,开发时间节省70%!
<dependencies>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.3.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.33version>
dependency>
dependencies>
# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/mp_demo?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
# 启用MP日志(查看执行SQL)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
// 实体类
@Data
@TableName("sys_user") // 映射表名
public class User {
@TableId(type = IdType.AUTO) // 自增主键
private Long id;
private String name;
private Integer age;
private String email;
}
// Mapper接口
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 无需写方法!
}
// 主类扫描Mapper
@SpringBootApplication
@MapperScan("com.example.mapper")
public class App { ... }
@SpringBootTest
class UserMapperTest {
@Autowired
private UserMapper userMapper;
// 插入
@Test
void testInsert() {
User user = new User(null, "李雷", 25, "[email protected]");
int rows = userMapper.insert(user); // 返回影响行数
System.out.println("插入ID:" + user.getId()); // 自动回填ID
}
// 查询
@Test
void testSelect() {
User user = userMapper.selectById(1); // 按ID查询
List<User> users = userMapper.selectList(Wrappers.<User>query()
.gt("age", 18)); // 条件查询
}
// 分页查询
@Test
void testPage() {
Page<User> page = new Page<>(1, 10); // 第1页,每页10条
userMapper.selectPage(page, Wrappers.emptyWrapper());
System.out.println("总记录数:" + page.getTotal());
}
}
场景:自动设置创建时间/更新时间
步骤:
// 1. 实体类标记填充字段
public class User {
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
// 2. 实现填充处理器
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class);
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
}
}
解决高并发数据更新冲突:
// 1. 实体类添加@Version字段
public class User {
@Version
private Integer version;
}
// 2. 配置乐观锁插件
@Configuration
public class MybatisPlusConfig {
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
// 3. 使用(自动校验版本号)
User user = userMapper.selectById(1);
user.setName("新名字");
userMapper.updateById(user); // WHERE id=1 AND version=oldVersion
数据不物理删除,标记删除状态:
# application.yml
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted # 全局删除标记字段
logic-delete-value: 1 # 删除值
logic-not-delete-value: 0 # 未删除值
// 实体类
public class User {
@TableLogic
private Integer deleted;
}
// 调用删除方法实际执行UPDATE
userMapper.deleteById(1);
// 实际SQL: UPDATE user SET deleted=1 WHERE id=1 AND deleted=0
最佳实践建议:新项目直接上MyBatis-Plus,老项目渐进式引入功能模块
最后的小测试:
MyBatis-Plus中哪个接口提供了基础CRUD方法?
A) BaseMapper
B) PageMapper
C) CrudRepository
(答案:A - BaseMapper是MyBatis-Plus的核心接口)
动手实践是最好的学习方式! 现在就创建一个Spring Boot项目体验MyBatis-Plus的魅力吧~