MyBatis-Plus复习

发布时间:2026/7/5 3:08:24
MyBatis-Plus复习 一、MyBatis-Plus 基础介绍1.1 框架简介MyBatis 是单表增删改查需要重复编写大量 XML 与 SQLMyBatis-Plus 在 MyBatis 基础上做无侵入增强无需修改原有 MyBatis 代码即可接入一键实现单表全部数据库操作大幅提升开发效率。复杂关联自定义 Mapper XML 编写原生关联 SQL简单关联Service 层多次单表查询业务组装数据。1.2 底层执行流程SpringBoot 启动扫描实体类反射读取TableName、TableId等注解解析表名、字段、主键、逻辑删除标识自动生成 insert/update/delete/select 标准 SQL 注入 MyBatis 容器开发者直接调用 BaseMapper 内置方法完成数据库交互。二、SpringBoot 快速整合 MyBatis-Plus 实战2.1 环境准备JDK8、SpringBoot2.x、MySQL8.0、Maven 项目2.2 数据库表初始化sqlDROP TABLE IF EXISTS user; CREATE TABLE user ( id BIGINT NOT NULL COMMENT 主键ID, name VARCHAR(30) NULL COMMENT 姓名, age INT NULL COMMENT 年龄, email VARCHAR(50) NULL COMMENT 邮箱, deleted INT DEFAULT 0 COMMENT 逻辑删除标记, version INT DEFAULT 0 COMMENT 乐观锁版本号, PRIMARY KEY (id) ); INSERT INTO user (id, name, age, email) VALUES (1, Jone, 18, test1baomidou.com), (2, Jack, 20, test2baomidou.com), (3, Tom, 28, test3baomidou.com);2.3 Maven 核心依赖xml!-- MySQL驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency !-- Lombok简化实体类 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- MyBatis-Plus启动器 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.2/version /dependency注意不可同时引入原生 MyBatis 依赖会造成冲突。2.4 application.yml 配置yamlspring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/boot?serverTimezoneAsia/ShanghaiuseUnicodetruecharacterEncodingUTF-8useSSLfalse username: root password: root mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印执行SQL global-config: db-config: id-type: assign_id # 默认雪花算法主键 logic-delete-field: deleted logic-delete-value: 1 # 已删除 logic-not-delete-value: 0 # 正常 mapper-locations: classpath:mapper/*.xml # 自定义XML路径2.5 实体类编写Data NoArgsConstructor AllArgsConstructor TableName(user) public class User { TableId(type IdType.ASSIGN_ID) private Long id; private String name; private Integer age; private String email; TableLogic private Integer deleted; Version private Integer version; }2.6 Mapper 接口与启动类Mapper 继承BaseMapper自动获得全部 CRUD 方法Mapper public interface UserMapper extends BaseMapperUser {}启动类使用MapperScan统一扫描 Mapper无需每个接口加MapperSpringBootApplication MapperScan(com.mp.mapper) public class MpApplication { public static void main(String[] args) { SpringApplication.run(MpApplication.class, args); } }2.7 基础测试查询SpringBootTest class MpTest { Autowired private UserMapper userMapper; Test void testSelectAll(){ ListUser list userMapper.selectList(null); list.forEach(System.out::println); } }运行控制台输出完整 SQL查询全部数据基础环境搭建完成。三、MyBatis-Plus 核心注解详解3.1 TableName绑定实体与数据库表实体类名和表名不一致时必须使用核心属性 value 指定表名。3.2 TableId 主键注解标记主键字段type 控制主键生成策略局部注解优先级高于全局配置AUTO数据库自增适合单体项目ASSIGN_ID雪花算法Long/String 类型分布式推荐默认策略ASSIGN_UUID32 位 UUID 字符串INPUT手动传入主键NONE跟随全局配置。雪花算法原理1 位符号位 41 位时间戳 10 位机器 ID12 位序列号分布式全局唯一。3.3 TableField普通字段注解常用场景value实体属性与数据库字段名不一致时映射existfalse标记该属性不属于数据库字段selectfalse查询时不返回该字段fill自动填充INSERT/UPDATE/INSERT_UPDATE。3.4 TableLogic逻辑删除字段标记开启后所有查询自动拼接where deleted0delete 操作转为 update 更新删除标记避免数据物理丢失。3.5 Version乐观锁版本号注解用于并发更新更新时自动携带版本条件防止数据覆盖丢失。四、BaseMapper 通用 CRUD 操作4.1 新增 insert ()插入实体使用雪花算法自动生成 ID 并回填至实体对象Test void testInsert(){ User user new User(); user.setName(张三); user.setAge(22); user.setEmail(zsqq.com); int rows userMapper.insert(user); System.out.println(受影响行数rows); System.out.println(自动生成IDuser.getId()); }4.2 更新操作updateById根据主键更新实体非 null 字段User user new User(); user.setId(1L); user.setName(张三修改); userMapper.updateById(user);update (entity, wrapper)自定义条件批量更新数据。4.3 查询常用方法// 根据主键单查 User user userMapper.selectById(1L); // 批量ID查询 ListUser list userMapper.selectBatchIds(Arrays.asList(1,2)); // Map等值多条件查询 MapString,Object map new HashMap(); map.put(name,Jack); ListUser userList userMapper.selectByMap(map); // 查询总条数 Integer total userMapper.selectCount(null);4.4 删除操作物理删除未开启逻辑删除deleteById、deleteBatchIds、deleteByMap逻辑删除全局配置 TableLogic执行 deleteById 不会删除数据SQL 变为update user set deleted1 where id? and deleted0。五、条件构造器 Wrapper复杂查询核心Wrapper 分为四类企业开发优先使用 Lambda 系列杜绝字段硬编码QueryWrapper普通字符串条件查询LambdaQueryWrapperLambda 表达式查询推荐UpdateWrapper自定义更新条件LambdaUpdateWrapperLambda 更新条件。常用查询示例// 1. 普通Wrapper年龄20~30姓名不为空 QueryWrapperUser wrapper new QueryWrapper(); wrapper.isNotNull(name).between(age,20,30).orderByDesc(id); ListUser list userMapper.selectList(wrapper); // 2. LambdaWrapper无硬编码推荐 LambdaQueryWrapperUser lambdaWrapper new LambdaQueryWrapper(); lambdaWrapper.ge(User::getAge, 20).likeRight(User::getEmail, t); ListUser lambdaList userMapper.selectList(lambdaWrapper);常用方法eq 等于、ne 不等于、gt 大于、ge 大于等于、lt 小于、le 小于等于、between 区间、like 模糊查询、orderByDesc 倒序。六、分页插件MP 内置物理分页无需引入 PageHelper只需配置拦截器。6.1 分页配置类Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // MySQL分页插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }6.2 分页代码使用Test void testPage(){ // 参数1当前页码参数2每页条数 PageUser page new Page(1,2); PageUser pageResult userMapper.selectPage(page, null); // 分页数据 ListUser records pageResult.getRecords(); // 分页信息 System.out.println(总条数pageResult.getTotal()); System.out.println(总页数pageResult.getPages()); System.out.println(是否下一页pageResult.hasNext()); }底层自动执行两条 SQLcount 统计总数 limit 分页查询。七、乐观锁解决并发更新丢失7.1 使用场景多线程同时修改同一条数据无锁会出现后提交的数据覆盖先提交数据造成数据丢失。乐观锁通过 version 版本号实现无锁并发控制。7.2 完整实现数据库添加 version 字段默认值 0实体 version 字段添加Version拦截器添加乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());并发测试逻辑// 两个线程读取同一条数据 Product p1 productMapper.selectById(1L); Product p2 productMapper.selectById(1L); // 线程1更新成功version自增1 p1.setPrice(p1.getPrice()500); productMapper.updateById(p1); // 线程2携带旧version更新匹配不到数据更新行数为0更新失败 p2.setPrice(p2.getPrice()-300); int rows productMapper.updateById(p2); if(rows 0){ // 业务重试重新查询最新数据再更新 }自动生成更新 SQLupdate product set price?,versionversion1 where id? and version?。八、Service 层通用封装 IServiceMP 在 Mapper 之上封装业务层通用接口命名区分 MapperMapper 用 select/insertService 用 list/get/save/remove。8.1 代码结构// Service接口 public interface UserService extends IServiceUser {} // 实现类 Service public class UserServiceImpl extends ServiceImplUserMapper, User implements UserService {}8.2 Service 常用方法Autowired private UserService userService; userService.save(user); // 新增 userService.saveBatch(list); // 批量新增 User user userService.getById(1L); // 根据id查询 ListUser list userService.list(wrapper); // 条件查询 IPageUser page userService.page(new Page(1,5), wrapper); // 分页查询 userService.saveOrUpdate(user); // 存在更新不存在新增九、自定义 SQL 处理复杂多表查询单表操作使用 MP 内置方法多表联查、复杂聚合 SQL 兼容原生 MyBatis XML。Mapper 接口定义自定义方法public interface UserMapper extends BaseMapperUser { ListUser selectByAge(Integer age); }resources/mapper 下创建 UserMapper.xmlxmlmapper namespacecom.mp.mapper.UserMapper select idselectByAge resultTypecom.mp.pojo.User select * from user where age #{age} /select /mapper十、代码生成器 AutoGenerator一键生成 controller、service、mapper、entity 全套代码大幅减少重复编码。10.1 新增依赖xmldependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.4.1/version /dependency dependency groupIdorg.apache.velocity/groupId artifactIdvelocity-engine-core/artifactId version2.3/version /dependency10.2 核心生成工具类public class MpGenerator { // 数据源配置 public static DataSourceConfig dataSource(){ DataSourceConfig ds new DataSourceConfig(); ds.setDbType(DbType.MYSQL); ds.setUrl(jdbc:mysql:///boot?serverTimezoneAsia/Shanghai); ds.setUsername(root); ds.setPassword(root); return ds; } // 全局配置 public static GlobalConfig globalConfig(){ GlobalConfig gc new GlobalConfig(); String path System.getProperty(user.dir); gc.setOutputDir(path/src/main/java); gc.setAuthor(作者); gc.setServiceName(%sService); return gc; } // 包配置 public static PackageConfig packageConfig(){ PackageConfig pc new PackageConfig(); pc.setParent(com.mp); pc.setController(controller); pc.setService(service); pc.setMapper(mapper); pc.setEntity(pojo); return pc; } // 策略配置 public static StrategyConfig strategy(){ StrategyConfig sc new StrategyConfig(); sc.setEntityLombokModel(true); sc.setLogicDeleteFieldName(deleted); sc.setVersionFieldName(version); sc.setNaming(NamingStrategy.underline_to_camel); sc.setInclude(user); // 指定生成表 return sc; } public static void main(String[] args) { AutoGenerator ag new AutoGenerator(); ag.setDataSource(dataSource()); ag.setGlobalConfig(globalConfig()); ag.setPackageInfo(packageConfig()); ag.setStrategy(strategy()); ag.execute(); } }运行 main 方法自动生成整套分层代码。