news 2026/2/23 2:20:32

MyBatis-Plus 你真的会用吗?90% 的人都踩过这些坑!(附正确姿势 + 反例)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MyBatis-Plus 你真的会用吗?90% 的人都踩过这些坑!(附正确姿势 + 反例)

视频看了几百小时还迷糊?关注我,几分钟让你秒懂!(发点评论可以给博主加热度哦)


一、为什么用 MyBatis-Plus?真实痛点 vs 神器

很多开发者还在手写 CRUD:

// 手写 Mapper XML,重复又易错 <select id="selectUserByName" resultType="User"> SELECT * FROM user WHERE name = #{name} </select>

MyBatis-Plus(MP)是什么?
✅ 它是 MyBatis 的增强工具,在MyBatis 的基础上只做增强,不做改变
✅ 自动注入通用 CRUD 方法,无需写 SQL,一行代码搞定增删改查!

🌰 场景:快速开发后台管理系统

  • 用户管理、商品管理、订单管理……
  • 每张表都要写 5~10 个基础接口
  • 时间紧、任务重、还要防 SQL 注入

MP 方案

// 继承 BaseMapper,直接拥有 20+ 个方法! public interface UserMapper extends BaseMapper<User> {}
// 查询名字为 "张三" 的用户 List<User> users = userMapper.selectList( new QueryWrapper<User>().eq("name", "张三") );

✅ 零 XML、零 SQL、类型安全、防注入!


二、Spring Boot + MyBatis-Plus 快速集成(正确姿势)

第一步:添加依赖(pom.xml

<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.5</version> </dependency> <!-- 数据库驱动(以 MySQL 为例) --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>

⚠️ 注意:不要同时引入mybatis-spring-boot-starter,MP 已包含!


第二步:配置application.yml

spring: datasource: url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8 username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL日志 global-config: db-config: id-type: auto # 主键自增 table-prefix: t_ # 表名前缀(如实体类 User 对应 t_user)

第三步:定义实体类(关键注解)

@Data @TableName("t_user") // 指定表名 public class User { @TableId(type = IdType.AUTO) // 主键策略 private Long id; @TableField("user_name") // 字段映射(数据库字段是 user_name) private String userName; private Integer age; @TableField(exist = false) // 非数据库字段(如密码确认) private String confirmPassword; }

第四步:Mapper 接口(一行代码,功能全有)

@Mapper public interface UserMapper extends BaseMapper<User> { // 无需写任何方法!BaseMapper 已提供: // insert, deleteById, updateById, selectById, selectList... }

第五步:Service 层(推荐使用 MP 的 IService)

@Service public class UserService implements IService<User> { @Autowired private UserMapper userMapper; // 可直接调用 getBaseMapper() 使用 CRUD public void demo() { // 插入 User user = new User(); user.setUserName("李四"); user.setAge(25); save(user); // 来自 IService // 查询 List<User> list = list(new QueryWrapper<User>() .ge("age", 18) .like("user_name", "李") ); } }

✅ 优势:IService提供更多便捷方法,如saveBatchupdateBatchById等。


三、高频反例 & 致命陷阱(90% 新手都中招!)

❌ 反例1:滥用select *,导致性能爆炸!

// 错误:查询所有字段,即使只需要 id 和 name List<User> users = userMapper.selectList(null);

✅ 正确:只查需要的字段

// 方式1:QueryWrapper.select() List<User> users = userMapper.selectList( new QueryWrapper<User>().select("id", "user_name") ); // 方式2:自定义 DTO + @Select @Select("SELECT id, user_name FROM t_user WHERE age > #{age}") List<UserDTO> selectSimpleUsers(@Param("age") int age);

❌ 反例2:手动拼接 SQL,引发注入漏洞!

// 危险!用户输入 "'; DROP TABLE t_user; --" 就完蛋了 String sql = "SELECT * FROM t_user WHERE name = '" + name + "'";

✅ 正确:永远使用 Wrapper 或参数绑定

// 安全!MP 自动参数化 userMapper.selectList(new QueryWrapper<User>().eq("user_name", name));

❌ 反例3:批量操作不用 MP 的 batch 方法 → 慢如蜗牛!

// 错误:循环单条插入(1万条 = 1万次数据库交互) for (User user : userList) { userMapper.insert(user); }

✅ 正确:使用saveBatch

userService.saveBatch(userList, 1000); // 分批提交,每批1000条

💡 原理:MP 内部使用ExecutorType.BATCH,极大提升性能。


❌ 反例4:逻辑删除配置错误 → 数据“假删”变“真丢”!

// 实体类未加 @TableLogic private Integer deleted; // 0-正常,1-删除

✅ 正确配置:

// 1. 实体类标注 @TableLogic private Integer deleted; // 2. 全局配置(application.yml) mybatis-plus: global-config: db-config: logic-delete-value: 1 # 删除值 logic-not-delete-value: 0 # 未删除值

🔍 效果:

  • userMapper.deleteById(1)→ 实际执行UPDATE ... SET deleted = 1
  • userMapper.selectById(1)→ 自动追加WHERE deleted = 0

❌ 反例5:分页插件未注册 → 分页失效!

// 直接调用 page 方法,结果返回全部数据! IPage<User> page = userService.page(new Page<>(1, 10));

✅ 正确:必须注册分页插件

@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusIntercepter(); // 注意拼写! interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }

⚠️ 注意:MP 3.4.0+ 使用MybatisPlusInterceptor,旧版用PaginationInterceptor


四、高级技巧:让 MP 更高效

1. 自动填充创建/更新时间

@TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class); this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class); } @Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class); } }

2. 乐观锁防止并发更新

@Version private Integer version; // 配置插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

五、总结:MyBatis-Plus 使用 Checklist

项目正确做法
依赖只引mybatis-plus-boot-starter
主键@TableId明确策略
字段映射@TableField处理下划线
查询QueryWrapper,禁止字符串拼接
批量saveBatch/updateBatchById
分页注册PaginationInnerInterceptor
逻辑删除配置@TableLogic+ 全局规则
性能避免select *,只查必要字段

MyBatis-Plus 不是“魔法”,而是规范 + 约定
用对了,开发效率翻倍;用错了,埋下性能炸弹!


视频看了几百小时还迷糊?关注我,几分钟让你秒懂!(发点评论可以给博主加热度哦)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/20 23:58:28

6.5 服务安全策略配置:mTLS和授权策略完整实现

6.5 服务安全策略配置:mTLS和授权策略完整实现 引言 安全是微服务架构的重要考虑。通过Istio的mTLS和授权策略,可以实现服务间的安全通信和访问控制。本文将详细介绍如何在Bookinfo中配置安全策略。 一、mTLS配置 1.1 启用mTLS apiVersion: security.istio.io/v1beta1 k…

作者头像 李华
网站建设 2026/2/21 15:55:04

JAVA校园跑腿系统,代买代拿轻松搞定

JAVA校园跑腿系统&#xff1a;代买代拿一键搞定&#xff0c;开启校园高效生活新篇章&#xff01;在校园里&#xff0c;你是否经常遇到这样的困扰&#xff1f;早八课前饿着肚子排队买早餐&#xff0c;结果差点迟到&#xff1b;网购的快递堆积如山&#xff0c;却因上课没时间取件…

作者头像 李华
网站建设 2026/2/22 13:37:32

今日立春:循千年咬春俗,守科学养生道

今日立春&#xff1a;循千年咬春俗&#xff0c;守科学养生道立春&#xff0c;作为岁时轮回的开端&#xff0c;标志着寒冬闭藏的结束与万物生发的开启。“咬春”作为立春最具代表性的民俗&#xff0c;承载着古人迎新春、祛寒气、助阳气、保安康的美好期许。一、立春调养&#xf…

作者头像 李华
网站建设 2026/2/20 6:05:58

41-parse的实现原理

parse 的实现原理 有限状态机 finite state machine 读取一组输入&#xff0c;然后根据这些输入来更改为不同的状态 state1 ---> state2------> state3简述 parse 的过程 // 初始状态 -----}}-----> 插值 ---> end ↓ // -----< a-z-----> parseEl…

作者头像 李华