ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

JDK 17与Spring Boot 3环境下MyBatisPlus整合实战与避坑指南

JDK 17与Spring Boot 3环境下MyBatisPlus整合实战与避坑指南 如果你正在使用 JDK 17 和 Spring Boot 3 开发新项目并且还在纠结于 MyBatis 繁琐的 XML 配置和样板代码那么这篇文章就是为你准备的。很多开发者以为在 Spring Boot 3 这个“新世界”里MyBatisPlus 只是简单地换个版本号就能跑起来但实际上一脚踩进去你会发现从依赖冲突、配置失效到新特性不兼容处处是坑。本文的核心判断是MyBatisPlus 与 Spring Boot 3 的整合绝不仅仅是版本升级而是一次涉及依赖管理、配置范式、新特性适配的“系统性迁移”。盲目照搬旧项目的配置大概率会让你在启动阶段就卡住。读完本文你将能清晰地知道如何从零开始在 JDK 17 Spring Boot 3 的环境下正确、高效地整合 MyBatisPlus并避开那些常见的“版本陷阱”。我们会从环境搭建、核心配置、代码生成一直讲到分页、枚举映射、字段加解密等高级特性确保你不仅能跑通 Demo更能理解背后的原理应用到实际生产项目中。1. 为什么是 JDK 17 Spring Boot 3 MyBatisPlus在开始动手之前我们需要先理解这个技术栈组合的价值和挑战。这不是一个随意的选择而是面向未来的技术决策。JDK 17是一个长期支持LTS版本带来了诸如密封类、模式匹配、新的垃圾收集器等语言和性能层面的增强。对于企业级应用选择 LTS 版本意味着更稳定的支持和更长的维护周期。Spring Boot 3是一个里程碑式的版本它基于 Spring Framework 6最低要求 JDK 17。它带来了全新的“Problem Details”错误处理机制、更完善的 GraalVM 原生镜像支持、以及将javax命名空间全面迁移到jakarta等重大变化。后者是整合 MyBatisPlus 时最需要关注的兼容性问题。MyBatisPlus是一个强大的 MyBatis 增强工具提供了通用的 Mapper、Service CRUD 接口、条件构造器、分页插件等功能能极大提升数据层开发效率。然而它的很多自动配置和插件依赖于 Spring Boot 的特定版本。核心挑战MyBatisPlus 的早期版本如 3.4.x, 3.5.x是为 Spring Boot 2.x 和javax包设计的。直接用在 Spring Boot 3 上会因为javax-jakarta的迁移而导致类找不到如javax.servlet.*或与 Spring Boot 3 内部的新机制不兼容。因此我们的首要任务是选择正确的 MyBatisPlus 版本。根据官方仓库和社区实践MyBatisPlus 3.5.3.1 及以上版本开始提供对 Spring Boot 3 的初步支持而最新的稳定版本如 3.5.7则提供了更完善的兼容性。本文将基于 MyBatisPlus 3.5.7 进行演示。2. 环境准备与项目初始化在开始编码前确保你的开发环境已就绪。这是后续所有步骤的基础。2.1 基础环境清单JDK: 17 或更高版本推荐 Oracle OpenJDK 17 或 Amazon Corretto 17。IDE: IntelliJ IDEA (2023.3 版本对 Spring Boot 3 支持更好) 或 Eclipse (需安装 Spring Tools)。构建工具: Maven (3.6) 或 Gradle (7.6)。本文使用 Maven。数据库: 任意MySQL 8.0、PostgreSQL 等。本文以 MySQL 8.0 为例。2.2 使用 Spring Initializr 快速创建项目最稳妥的方式是通过 start.spring.io 生成项目骨架。访问 start.spring.io。选择以下配置Project: Maven ProjectLanguage: JavaSpring Boot: 3.2.5 (选择最新的稳定版)Project Metadata: 根据你的情况填写 Group、Artifact 等信息。Packaging: JarJava: 17在Dependencies中先添加Spring Web(用于构建Web应用)MySQL Driver(数据库驱动)Lombok(简化实体类代码可选但推荐)点击Generate下载项目压缩包并导入到你的 IDE 中。此时你得到了一个纯净的 Spring Boot 3 项目。接下来我们需要手动添加 MyBatisPlus 的依赖。2.3 关键依赖配置pom.xml打开项目中的pom.xml文件在dependencies部分添加 MyBatisPlus 的 Starter 依赖。核心要点必须使用与 Spring Boot 3 兼容的mybatis-plus-boot-starter版本。不要引入旧的mybatis-plus-boot-starter。!-- 在已有的 dependencies 标签内添加 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.7/version !-- 关键使用兼容 Spring Boot 3 的版本 -- /dependency !-- 数据库驱动 (如果Initializr已添加则无需重复) -- dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency !-- Lombok (如果Initializr已添加则无需重复) -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency依赖冲突排查添加依赖后建议执行mvn dependency:tree命令检查是否有低版本的 MyBatis 或其它冲突的依赖被传递进来。Spring Boot 3 默认管理 MyBatis 的版本而 MyBatisPlus Starter 会覆盖它这通常是良性的。3. 核心配置详解连接数据库与 MyBatisPlus配置是整合的关键环节。Spring Boot 3 的配置方式与 2.x 基本一致但属性前缀和默认值可能有细微差别。3.1 数据库连接配置 (application.yml)在src/main/resources/application.yml中配置数据库连接。推荐使用 YAML 格式因为它结构更清晰。spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/mybatisplus_demo?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: yourpassword # MyBatisPlus 相关配置 mybatis-plus: configuration: # 控制台打印完整带参数SQL开发环境使用 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启驼峰命名自动映射数据库下划线字段 - 实体类驼峰属性 map-underscore-to-camel-case: true global-config: db-config: # 全局主键类型AUTO(数据库自增) INPUT(手动输入) ASSIGN_ID(雪花算法) ASSIGN_UUID(UUID) id-type: ASSIGN_ID # 逻辑删除字段名非必须按需配置 logic-delete-field: isDeleted # 逻辑已删除值默认为 1 logic-delete-value: 1 # 逻辑未删除值默认为 0 logic-not-delete-value: 0 # 指定 Mapper XML 文件位置如果你有自定义的复杂SQL mapper-locations: classpath*:/mapper/**/*.xml配置解释log-impl: StdOutImpl这是排查 SQL 问题的利器。在开发阶段开启可以清晰看到 MyBatisPlus 最终执行的 SQL 语句及其参数。生产环境务必关闭。id-type: ASSIGN_ID这是 MyBatisPlus 的推荐配置。它使用雪花算法生成分布式 ID避免数据库自增 ID 在分库分表或数据迁移时的局限性。逻辑删除通过配置一个字段如is_deleted来标记记录是否删除而非物理删除。MyBatisPlus 会自动在查询中加上WHERE is_deleted0条件在删除操作时执行UPDATE SET is_deleted1。3.2 主启动类与 Mapper 扫描确保你的主启动类通常是XxxApplication.java上添加了MapperScan注解用于扫描 MyBatis 的 Mapper 接口。// 文件路径src/main/java/com/example/demo/DemoApplication.java package com.example.demo; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; SpringBootApplication MapperScan(com.example.demo.mapper) // 指定你的 Mapper 接口所在的包 public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }注意MapperScan是 MyBatis 原生的注解在mybatis-spring-boot-starter中。MyBatisPlus 的 Starter 包含了它所以可以直接使用。如果忘记添加启动时会报NoSuchBeanDefinitionException提示找不到 Mapper 的 Bean。4. 实体、Mapper 与 Service 的快速生成MyBatisPlus 的核心魅力在于其强大的 CRUD 封装。我们通过一个User实体来演示。4.1 创建实体类 (Entity)使用 Lombok 简化代码。// 文件路径src/main/java/com/example/demo/entity/User.java package com.example.demo.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.time.LocalDateTime; Data TableName(sys_user) // 指定表名如果表名与类名一致忽略大小写和下划线可省略 public class User { /** * 主键 * TableId 注解用于标识主键 * type IdType.ASSIGN_ID 表示使用雪花算法生成ID */ TableId(type IdType.ASSIGN_ID) private Long id; /** * 用户名 */ private String username; /** * 密码 */ private String password; /** * 邮箱 */ private String email; /** * 创建时间 * TableField 注解用于配置字段与数据库列的映射关系 * fill FieldFill.INSERT 表示在插入操作时自动填充 */ TableField(fill FieldFill.INSERT) private LocalDateTime createTime; /** * 更新时间 * fill FieldFill.INSERT_UPDATE 表示在插入和更新操作时自动填充 */ TableField(fill FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; /** * 逻辑删除标记 (0-未删除 1-已删除) * 需要配合全局配置 mybatis-plus.global-config.db-config.logic-delete-field 使用 */ TableLogic private Integer isDeleted; }注解说明TableName: 实体类对应的数据库表名。TableId: 主键注解。IdType.ASSIGN_ID是 MyBatisPlus 3.3.0 后推荐的分布式 ID 策略。TableField: 字段注解。fill属性配合元对象处理器MetaObjectHandler可以实现自动填充创建时间、更新时间等字段。TableLogic: 逻辑删除注解。标记此字段为逻辑删除标志位。4.2 创建 Mapper 接口Mapper 接口只需继承 MyBatisPlus 提供的BaseMapper即可获得全套单表 CRUD 方法。// 文件路径src/main/java/com/example/demo/mapper/UserMapper.java package com.example.demo.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.demo.entity.User; public interface UserMapper extends BaseMapperUser { // 无需编写任何方法即可拥有 insert, selectById, updateById, deleteById, selectList 等方法。 // 如果需要复杂查询可以在此处定义方法并在 resources/mapper/UserMapper.xml 中编写SQL。 }4.3 创建 Service 接口及其实现Service 层可以继承IService和ServiceImpl获得更丰富的批量操作和链式查询方法。// 文件路径src/main/java/com/example/demo/service/UserService.java package com.example.demo.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.demo.entity.User; public interface UserService extends IServiceUser { // 可以在此定义业务特有的方法 // User getByUsername(String username); }// 文件路径src/main/java/com/example/demo/service/impl/UserServiceImpl.java package com.example.demo.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.demo.entity.User; import com.example.demo.mapper.UserMapper; import com.example.demo.service.UserService; import org.springframework.stereotype.Service; Service // 不要忘记加Service注解 public class UserServiceImpl extends ServiceImplUserMapper, User implements UserService { // 如果 UserService 接口有自定义方法需要在这里实现 // Override // public User getByUsername(String username) { // return this.lambdaQuery().eq(User::getUsername, username).one(); // } }至此最基本的 CRUD 功能已经具备。你可以通过注入UserMapper或UserService来操作User表。5. 自动填充与元对象处理器我们之前在User实体中定义了createTime和updateTime的自动填充规则现在需要实现MetaObjectHandler来定义填充的内容。// 文件路径src/main/java/com/example/demo/handler/MyMetaObjectHandler.java package com.example.demo.handler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; import java.time.LocalDateTime; Component // 必须声明为Spring组件 public class MyMetaObjectHandler implements MetaObjectHandler { /** * 插入操作时自动填充 */ Override public void insertFill(MetaObject metaObject) { // 判断是否有 createTime 字段且该字段值为空 if (metaObject.hasSetter(createTime)) { this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now()); } // 更新时间的插入填充 if (metaObject.hasSetter(updateTime)) { this.strictInsertFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); } } /** * 更新操作时自动填充 */ Override public void updateFill(MetaObject metaObject) { // 判断是否有 updateTime 字段 if (metaObject.hasSetter(updateTime)) { this.strictUpdateFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); } } }关键点strictInsertFill和strictUpdateFill是 MyBatisPlus 3.3.0 后推荐的方法它们要求明确指定字段的Class类型避免了类型推断错误。当执行userMapper.insert(user)或userService.updateById(user)时对应的时间字段会被自动填充为当前时间。6. 核心功能实战条件构造器与分页查询MyBatisPlus 的条件构造器QueryWrapper,LambdaQueryWrapper,UpdateWrapper和分页插件是其最常用的高级功能。6.1 条件构造器使用示例假设我们需要查询邮箱包含 “example.com” 且创建时间在 2024 年之后的用户列表。// 在 Service 或 Controller 中注入 UserService Autowired private UserService userService; public void testQueryWrapper() { // 方式一使用 LambdaQueryWrapper (推荐类型安全避免硬编码字段名) LambdaQueryWrapperUser lambdaQuery new LambdaQueryWrapper(); lambdaQuery.like(User::getEmail, example.com) .ge(User::getCreateTime, LocalDateTime.of(2024, 1, 1, 0, 0)) .orderByDesc(User::getCreateTime); ListUser userList1 userService.list(lambdaQuery); // 方式二使用 QueryWrapper (字段名用字符串灵活性高但容易写错) QueryWrapperUser queryWrapper new QueryWrapper(); queryWrapper.like(email, example.com) .ge(create_time, LocalDateTime.of(2024, 1, 1, 0, 0)) .orderByDesc(create_time); ListUser userList2 userService.list(queryWrapper); // 链式调用 lambda 查询 (更简洁) ListUser userList3 userService.lambdaQuery() .like(User::getEmail, example.com) .ge(User::getCreateTime, LocalDateTime.of(2024, 1, 1, 0, 0)) .orderByDesc(User::getCreateTime) .list(); }强烈推荐使用LambdaQueryWrapper因为它通过方法引用来获取字段名在编译期就能检查错误重构代码时也更安全。6.2 分页插件配置与使用MyBatisPlus 的分页功能需要先配置一个分页插件Interceptor。// 文件路径src/main/java/com/example/demo/config/MybatisPlusConfig.java package com.example.demo.config; import com.baomidou.mybatisplus.annotation.DbType; 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 { /** * 添加 MyBatisPlus 插件 * 注意在 Spring Boot 3 中旧版的 PaginationInterceptor 已废弃必须使用 MybatisPlusInterceptor */ Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 添加分页插件并指定数据库类型这里是MySQL interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 还可以添加其他插件如乐观锁插件 // interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } }配置好插件后就可以在 Service 或 Mapper 中使用分页查询了。public void testPagination() { // 构建分页参数查询第1页每页10条 PageUser page new Page(1, 10); // 构建查询条件 LambdaQueryWrapperUser queryWrapper new LambdaQueryWrapper(); queryWrapper.isNotNull(User::getEmail); // 执行分页查询 PageUser resultPage userService.page(page, queryWrapper); // 获取分页数据 ListUser records resultPage.getRecords(); // 当前页数据列表 long total resultPage.getTotal(); // 总记录数 long pages resultPage.getPages(); // 总页数 long current resultPage.getCurrent(); // 当前页码 long size resultPage.getSize(); // 每页大小 System.out.println(总记录数: total); System.out.println(当前页数据: records); }关于“单页500条限制”这是一个常见的误解。MyBatisPlus 分页插件本身没有硬性限制。所谓的“500条限制”通常来自前端或 API 网关的配置或者开发者自己出于性能考虑在业务代码中做的限制。如果你需要查询大量数据应使用Page对象正常分页或者考虑使用limit进行流式查询。插件只是帮你把Page对象转换为数据库的LIMIT语句。7. 高级特性枚举映射与字段加解密7.1 枚举映射将数据库的 tinyint 或 varchar 字段映射为 Java 枚举能极大提升代码的可读性和健壮性。MyBatisPlus 提供了EnumValue注解。定义枚举类// 文件路径src/main/java/com/example/demo/enums/UserStatusEnum.java package com.example.demo.enums; import com.baomidou.mybatisplus.annotation.EnumValue; import lombok.Getter; Getter public enum UserStatusEnum { DISABLED(0, 禁用), ENABLED(1, 启用); // EnumValue 标记存储到数据库的值 EnumValue private final Integer code; private final String desc; UserStatusEnum(Integer code, String desc) { this.code code; this.desc desc; } }在实体类中使用枚举// 在 User 实体类中添加字段 public class User { // ... 其他字段 private UserStatusEnum status; // 数据库对应字段可以是 status int类型 }在配置中开启枚举处理application.ymlmybatis-plus: configuration: # 开启枚举类型处理 default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler好处存入数据库的是0或1但在 Java 代码中你操作的是UserStatusEnum.ENABLED这样的对象避免了魔法数字也方便了状态判断和国际化。7.2 字段自动加解密拦截器对于密码、手机号、身份证号等敏感信息我们希望在存入数据库时自动加密查询时自动解密。这可以通过实现 MyBatis 的TypeHandler或使用拦截器完成。这里展示一个基于TypeHandler的简单 AES 加解密示例。创建加解密工具类生产环境请使用更安全的密钥管理方式// 文件路径src/main/java/com/example/demo/handler/encrypt/AesEncryptor.java package com.example.demo.handler.encrypt; import org.springframework.util.Base64Utils; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; public class AesEncryptor { private static final String ALGORITHM AES/ECB/PKCS5Padding; private static final byte[] KEY MySuperSecretKey16.getBytes(StandardCharsets.UTF_8); // 16字节密钥 public static String encrypt(String data) throws Exception { SecretKeySpec secretKey new SecretKeySpec(KEY, AES); Cipher cipher Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] encryptedBytes cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); return Base64Utils.encodeToString(encryptedBytes); } public static String decrypt(String encryptedData) throws Exception { SecretKeySpec secretKey new SecretKeySpec(KEY, AES); Cipher cipher Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] decryptedBytes cipher.doFinal(Base64Utils.decodeFromString(encryptedData)); return new String(decryptedBytes, StandardCharsets.UTF_8); } }创建自定义 TypeHandler// 文件路径src/main/java/com/example/demo/handler/encrypt/EncryptTypeHandler.java package com.example.demo.handler.encrypt; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class EncryptTypeHandler extends BaseTypeHandlerString { Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { try { // 存入数据库前加密 ps.setString(i, AesEncryptor.encrypt(parameter)); } catch (Exception e) { throw new SQLException(加密字段失败, e); } } Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { String encrypted rs.getString(columnName); return decryptString(encrypted); } Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String encrypted rs.getString(columnIndex); return decryptString(encrypted); } Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String encrypted cs.getString(columnIndex); return decryptString(encrypted); } private String decryptString(String encrypted) { if (encrypted null) { return null; } try { return AesEncryptor.decrypt(encrypted); } catch (Exception e) { // 解密失败可能该字段原本就不是加密数据直接返回原值根据业务调整 return encrypted; } } }在实体类字段上应用 TypeHandler// 在 User 实体类的 password 字段上添加注解 public class User { // ... TableField(typeHandler EncryptTypeHandler.class) private String password; // ... }这样当你调用userService.save(user)时password字段在存入数据库前会自动加密。当通过userService.getById(1L)查询时password字段会自动解密。注意此方案仅对通过 MyBatisPlus 进行的操作生效。直接运行 SQL 或通过其他方式操作数据库则不会触发加解密。8. 常见问题与排查思路在整合过程中你可能会遇到以下问题。这里提供一个快速排查指南。问题现象可能原因排查方式解决方案启动报错java.lang.ClassNotFoundException: javax.servlet...MyBatisPlus 版本与 Spring Boot 3 不兼容引用了javax包。检查pom.xml中mybatis-plus-boot-starter的版本。升级到3.5.3.1或更高版本。启动报错Failed to configure a DataSource未配置数据库连接或配置有误。检查application.yml中的spring.datasource配置。1. 确认数据库服务已启动。2. 检查URL、用户名、密码是否正确。3. 添加spring.autoconfigure.exclude...排除数据源自动配置仅在不需DB时。Mapper 接口注入失败NoSuchBeanDefinitionExceptionMapperScan注解未添加或扫描路径错误。1. 检查主启动类是否有MapperScan。2. 检查路径是否包含所有 Mapper 接口。在主启动类添加MapperScan(你的.mapper包路径)。分页查询不生效返回所有数据分页插件MybatisPlusInterceptor未配置。检查是否创建了配置类并添加了PaginationInnerInterceptor。参照第6.2节创建MybatisPlusConfig配置类。自动填充如 createTime不生效MetaObjectHandler未声明为Component或字段注解fill属性配置错误。1. 检查MyMetaObjectHandler类是否有Component。2. 检查实体类字段的TableField(fill ...)注解。确保处理器是 Spring Bean且填充策略INSERT/UPDATE与操作匹配。控制台不打印 SQL 日志未在配置中开启日志或日志级别设置不正确。检查application.yml中mybatis-plus.configuration.log-impl配置。设置为org.apache.ibatis.logging.stdout.StdOutImpl。同时检查 Spring Boot 的logging.level.com.example.demo.mapperDEBUG。使用LambdaQueryWrapper时报错can’t find lambda cache可能是在非 Spring 管理的类如普通的 Util 类中使用了 Lambda 表达式。确认使用 Lambda 表达式的代码在 Spring Bean如Service,Component中。将相关逻辑移到 Spring 管理的 Bean 中或改用QueryWrapper并手动写字段名字符串。更新操作后updateTime未自动更新MetaObjectHandler的updateFill方法未正确实现或更新时未使用 MyBatisPlus 的updateById等方法。1. 检查updateFill方法逻辑。2. 确认更新操作调用的是userService.updateById(user)而非自己写UPDATESQL。确保updateFill方法被调用并使用 MyBatisPlus 的更新方法。9. 生产环境最佳实践与建议将 MyBatisPlus 用于生产环境除了跑通功能还需要关注稳定性、性能和可维护性。版本管理在pom.xml中使用properties统一管理关键依赖版本特别是 MyBatisPlus 和 MyBatis 的版本避免潜在的冲突。properties mybatis-plus.version3.5.7/mybatis-plus.version mybatis.version3.5.16/mybatis.version /properties dependencies dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version${mybatis-plus.version}/version /dependency /dependencies关闭开发环境日志生产环境务必关闭log-impl: StdOutImpl改为使用 SLF4J 并配置适当的日志级别避免泄露敏感信息和影响性能。mybatis-plus: configuration: # 生产环境注释掉或删除此行 # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl复杂 SQL 使用 XML对于多表关联、复杂统计等查询不要强行用QueryWrapper拼接。应遵循 MyBatis 的传统在 XML 文件中编写清晰、可维护的 SQL并在 Mapper 接口中定义方法。批量操作性能MyBatisPlus 的Service层提供了saveBatch、updateBatchById等方法但其默认实现可能不是真正的批量提交例如可能是循环单条插入。对于大数据量批量操作建议使用自定义的SqlSession批量模式或评估使用ExecutorType.BATCH。逻辑删除的注意事项一旦启用逻辑删除所有delete操作都将变为update所有select操作都会自动加上WHERE is_deleted0。如果需要查询已删除的数据可以使用TableLogic注解的delval和value属性或使用Wrapper手动覆盖条件。监控与审计考虑使用 MyBatisPlus 的SQL 注入分析插件(BlockAttackInnerInterceptor) 来防止全表更新/删除。对于关键数据变更可以结合 Spring AOP 或 MyBatis 的插件机制实现操作日志审计。代码生成器对于大型项目可以使用 MyBatisPlus 的代码生成器 (AutoGenerator)来快速生成 Entity、Mapper、Service、Controller 层代码。这能极大提升初期开发效率但生成的代码可能需要根据项目规范进行二次调整。使用前请仔细阅读官方文档配置好数据源、包路径和策略。整合 JDK 17、Spring Boot 3 和 MyBatisPlus 是一个典型的“新版本栈”实践其核心在于理解版本间的兼容性变化并正确配置依赖和核心组件。从环境搭建、基础 CRUD、到条件构造器、分页、枚举映射、字段加解密这套组合拳能覆盖绝大多数业务场景的开发需求。记住遇到问题首先检查版本其次是配置最后才是代码逻辑。把本文中的配置和代码作为你的项目起点根据实际业务进行裁剪和深化你就能在 Spring Boot 3 的新生态中继续享受 MyBatisPlus 带来的高效与便捷。
返回列表