简介:这份资源是面向Java后端开发者与初学者的Spring Boot 3整合MyBatisPlus实战示例工程,针对企业级Web应用中数据访问层配置繁琐、CRUD模板代码重复等痛点,提供一套可直接运行的整合方案。压缩包共24个文件,约85KB,包含7个Java源码、7个class编译文件、2个yaml配置、1个properties、1个pom.xml及mvnw构建脚本等,覆盖依赖管理、数据源配置、Mapper接口、实体注解与Service、Controller分层结构,目录组织清晰,便于对照学习。目前已有1435人学习下载,说明该整合方案在开发者社区中具有较高的参考价值。读者可从中获取Spring Boot 3与MyBatisPlus协同工作的完整工程骨架,理解BaseMapper通用CRUD、条件构造器与自动填充等核心用法,并可直接基于该结构扩展业务模块,减少重复搭建环境的时间成本。1. Spring Boot 3 整合 MyBatis-Plus:从 JDK 17 到分页插件跑通很多人第一次在 Spring Boot 3 里配 MyBatis-Plus,都会卡在同一个地方:依赖能下、项目能起,但一调 Mapper 就报Invalid bound statement,或者分页查出来总数永远是 0。这不是代码写错了,而是 Spring Boot 3 把底层依赖整体抬到了 JDK 17 和 Jakarta EE 9+,而 MyBatis-Plus 的 starter 如果版本没跟上,扫描和自动装配就会静默失效。这套组合在后台管理系统、数据中台、内部工具里出现频率极高,几乎每个 Java 后端都会碰到。下面按我实际装环境的顺序,把 JDK、Maven、依赖、配置、分页和排错一次讲清,照着走能少熬两个晚上。2. 环境准备:JDK 17、Maven 与 Spring Boot 3 的版本对齐2.1 为什么必须是 JDK 17 起步Spring Boot 3 的最低要求是 JDK 17,这不是建议,是硬门槛。用 JDK 8 或 11 编译,spring-boot-starter-web里的jakarta.servlet包根本加载不了,启动直接抛NoClassDefFoundError。我一般用 Temurin 17 或 21,LTS 版本稳定,IDE 里把编译级别和运行级别都设成 17。# 检查当前 JDK 版本,必须 >= 17 java -version # 输出示例:openjdk version "17.0.9" 2023-10-17 # 如果系统有多个 JDK,用 JAVA_HOME 显式指定 export JAVA_HOME=/usr/lib/jvm/temurin-17-jdk export PATH=$JAVA_HOME/bin:$PATHjava -version看的是运行时,javac -version看的是编译器,两个都要确认。Maven 编译时用的是JAVA_HOME指向的 JDK,如果 IDE 里配了别的,会出现命令行能编译、IDE 报错的玄学问题。2.2 Maven 版本与镜像配置Maven 用 3.8 以上即可,3.9 更稳。关键是settings.xml里配好镜像,否则拉 Spring Boot 3 的依赖会慢到怀疑人生。<!-- ~/.m2/settings.xml 片段 --> <mirrors> <mirror> <id>aliyun-central</id> <mirrorOf>central</mirrorOf> <name>aliyun central</name> <url>https://maven.aliyun.com/repository/central</url> </mirror> </mirrors>mirrorOf写central表示只代理中央仓库,不要写*,否则连公司私服也会被劫持。配完后执行mvn help:effective-settings确认镜像生效。2.3 版本对照表:别让 starter 版本打架Spring Boot 3 和 MyBatis-Plus 的版本必须成对选,下面是我验证过能跑通的组合:组件推荐版本说明JDK17 / 21LTS,21 性能更好Spring Boot3.2.x3.0/3.1 也可,3.2 最稳MyBatis-Plus3.5.5+必须用mybatis-plus-spring-boot3-starterMySQL 驱动8.0.33+用com.mysql.cj.jdbc.DriverLombok1.18.30+低版本在 JDK 21 下会编译失败最容易翻车的是 starter 名字:Spring Boot 3 要用mybatis-plus-spring-boot3-starter,不是老的mybatis-plus-boot-starter。用错了不会报错,只会扫描不到 Mapper。3. 依赖引入与 application.yml 配置落地3.1 pom.xml 里到底写哪几个依赖父工程锁定 Spring Boot 版本,子模块只引 starter,不要手动指定 MyBatis-Plus 的版本号,交给 BOM 管理。<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.5</version> <relativePath/> </parent> <dependencies> <!-- Web 基础,Spring Boot 3 自带 jakarta 命名空间 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 关键:Spring Boot 3 专用 starter,别用错 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.5</version> </dependency> <!-- MySQL 驱动,scope 用 runtime --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>mybatis-plus-spring-boot3-starter内部已经带了mybatis-spring和mybatis,不要再单独引mybatis-spring-boot-starter,两个一起引会导致自动配置冲突,启动时报BeanDefinitionOverrideException。3.2 application.yml 的最小可用配置spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/demo_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: your_password mybatis-plus: # Mapper XML 位置,多个路径用逗号分隔 mapper-locations: classpath*:/mapper/**/*.xml # 实体类别名包,XML 里可直接写类名 type-aliases-package: com.example.demo.entity configuration: # 下划线转驼峰,数据库 user_name -> 实体 userName map-underscore-to-camel-case: true # 开发期打印 SQL,上线关掉 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: # 主键自增,实体不写 @TableId 也能识别 id-type: automapper-locations里的classpath*:带星号,表示扫描所有 jar 和目录下的匹配文件,漏了星号在多模块项目里只能扫到当前模块。serverTimezone必须写,不写 MySQL 8 会报时区错误。3.3 启动类加 @MapperScan@SpringBootApplication @MapperScan("com.example.demo.mapper") // 扫描 Mapper 接口 public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }@MapperScan的包路径要精确到 mapper 接口所在包,不要写com.example.demo这种大范围,否则会把 Service 也当 Mapper 扫描,启动报No statement found。如果每个 Mapper 上都加了@Mapper,可以省略这个注解,但多模块下我建议统一用@MapperScan,省得漏。4. 分页插件与代码生成器:两个最容易配错的模块4.1 分页插件必须手动注册MyBatis-Plus 3.5.x 的分页插件不会自动生效,必须写配置类。不注册的话Page查询返回全部数据,total为 0,这是最高频的坑。@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 分页插件,指定数据库类型 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 乐观锁插件,按需加 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } }DbType.MYSQL要和你实际数据库一致,写成DbType.OTHER分页 SQL 会拼错。多个内部拦截器有顺序要求:分页插件放最后加,否则可能被其他拦截器改写 SQL 导致分页失效。4.2 分页查询的写法与验证// Service 层 public IPage<User> pageQuery(int pageNum, int pageSize) { Page<User> page = new Page<>(pageNum, pageSize); // 第二个参数是查询条件,null 表示查全部 return userMapper.selectPage(page, null); }Page的pageNum从 1 开始,不是 0。传 0 会返回空列表但不报错,很容易误判成没数据。验证时看控制台打印的 SQL 有没有LIMIT,有LIMIT且total正确,说明插件生效。4.3 代码生成器在 Spring Boot 3 下的调整MyBatis-Plus 的代码生成器依赖freemarker和velocity,Spring Boot 3 下要单独引,且模板引擎版本要新。FastAutoGenerator.create(url, username, password) .globalConfig(builder -> builder .author("dev") .outputDir(System.getProperty("user.dir") + "/src/main/java") .disableOpenDir()) // 生成后不自动打开目录 .packageConfig(builder -> builder .parent("com.example.demo") .entity("entity") .mapper("mapper") .service("service")) .strategyConfig(builder -> builder .addInclude("user", "order") // 指定表名 .entityBuilder().enableLombok()) .execute();outputDir用user.dir相对路径,别写死绝对路径,换机器就废。addInclude不写会生成全库所有表,生产库上跑一次能生成几百个文件。5. 避坑排查:整合后启动报错的五条血泪记录5.1 现象:Invalid bound statement (not found)原因:Mapper 接口和 XML 没对上。要么mapper-locations路径写错,要么 XML 的namespace不是接口全限定名,要么 XML 放在src/main/java下没配资源过滤。解决:先看target/classes/mapper下有没有 XML 文件,没有就是资源没打包。在pom.xml的<build>里加:<resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources>5.2 现象:分页 total 为 0,数据却查出来了原因:分页插件没注册,或者注册了但DbType写错。还有一种情况是自定义 SQL 里用了UNION,分页插件生成的 count 语句不兼容。解决:确认MybatisPlusInterceptor被 Spring 扫描到,自定义复杂 SQL 手动写 count 查询,用page.setTotal()设置。5.3 现象:启动报 jakarta.servlet 相关 ClassNotFound原因:引了老的javax.servlet依赖,或者某个第三方库还在用 javax。解决:mvn dependency:tree | grep javax.servlet找出冲突源,排除掉。Spring Boot 3 下所有 servlet 相关依赖都必须是 jakarta 版本。5.4 现象:Lombok 编译报错,提示找不到符号原因:Lombok 版本低于 1.18.30,在 JDK 21 下注解处理器不工作。解决:升级 Lombok 到 1.18.30+,并在maven-compiler-plugin里显式配置注解处理器路径。5.5 现象:多模块下子模块 Mapper 扫描不到原因:@MapperScan只写在启动类所在模块,子模块的 Mapper 包不在扫描范围。解决:@MapperScan写多个包路径,或者用@MapperScan(basePackages = {"com.example.module1.mapper", "com.example.module2.mapper"})。6. 装完怎么验证:三条命令确认整合真的跑通环境装完别急着写业务,先跑一遍验证。我一般按下面三步走,任何一步不过就回去查对应配置。第一步,启动应用看日志。控制台出现MyBatis-Plus的 banner 和Started DemoApplication才算启动成功。如果看到No MyBatis mapper was found的警告,说明@MapperScan路径不对。第二步,调一个分页接口,看控制台 SQL。正常应该打印两条:一条SELECT COUNT(*),一条带LIMIT的查询。只有一条带LIMIT的,说明分页插件没生效。# 用 curl 验证分页接口 curl "http://127.0.0.1:8080/user/page?pageNum=1&pageSize=10" # 期望返回:{"records":[...],"total":100,"size":10,"current":1}total是真实总数,records长度等于pageSize,current等于传入的pageNum,三个都对才算过。第三步,验证 XML 自定义 SQL。写一个带resultMap的查询,确认字段映射正确。如果返回对象字段全是 null,检查map-underscore-to-camel-case是否开启,以及 XML 里resultType写的是不是全限定名。验证项通过标准失败先查应用启动无 Mapper 警告@MapperScan 路径分页查询有 COUNT 和 LIMIT分页插件注册XML 查询字段有值mapper-locations主键回填insert 后 id 有值id-type 配置从那以后我每次搭 Spring Boot 3 加 MyBatis-Plus 的环境,都强制先跑这三步再写业务代码,省得写到一半发现分页是坏的、字段映射是错的,回头返工更费时间。希望帮到你。本文还有配套的精品资源,点击获取
简介:这份资源是面向Java后端开发者与初学者的Spring Boot 3整合MyBatisPlus实战示例工程,针对企业级Web应用中数据访问层配置繁琐、CRUD模板代码重复等痛点,提供一套可直接运行的整合方案。压缩包共24个文件,约85KB,包含7个Java源码、7个class编译文件、2个yaml配置、1个properties、1个pom.xml及mvnw构建脚本等,覆盖依赖管理、数据源配置、Mapper接口、实体注解与Service、Controller分层结构,目录组织清晰,便于对照学习。目前已有1435人学习下载,说明该整合方案在开发者社区中具有较高的参考价值。读者可从中获取Spring Boot 3与MyBatisPlus协同工作的完整工程骨架,理解BaseMapper通用CRUD、条件构造器与自动填充等核心用法,并可直接基于该结构扩展业务模块,减少重复搭建环境的时间成本。1. Spring Boot 3 整合 MyBatis-Plus:从 JDK 17 到分页插件跑通很多人第一次在 Spring Boot 3 里配 MyBatis-Plus,都会卡在同一个地方:依赖能下、项目能起,但一调 Mapper 就报Invalid bound statement,或者分页查出来总数永远是 0。这不是代码写错了,而是 Spring Boot 3 把底层依赖整体抬到了 JDK 17 和 Jakarta EE 9+,而 MyBatis-Plus 的 starter 如果版本没跟上,扫描和自动装配就会静默失效。这套组合在后台管理系统、数据中台、内部工具里出现频率极高,几乎每个 Java 后端都会碰到。下面按我实际装环境的顺序,把 JDK、Maven、依赖、配置、分页和排错一次讲清,照着走能少熬两个晚上。2. 环境准备:JDK 17、Maven 与 Spring Boot 3 的版本对齐2.1 为什么必须是 JDK 17 起步Spring Boot 3 的最低要求是 JDK 17,这不是建议,是硬门槛。用 JDK 8 或 11 编译,spring-boot-starter-web里的jakarta.servlet包根本加载不了,启动直接抛NoClassDefFoundError。我一般用 Temurin 17 或 21,LTS 版本稳定,IDE 里把编译级别和运行级别都设成 17。# 检查当前 JDK 版本,必须 >= 17 java -version # 输出示例:openjdk version "17.0.9" 2023-10-17 # 如果系统有多个 JDK,用 JAVA_HOME 显式指定 export JAVA_HOME=/usr/lib/jvm/temurin-17-jdk export PATH=$JAVA_HOME/bin:$PATHjava -version看的是运行时,javac -version看的是编译器,两个都要确认。Maven 编译时用的是JAVA_HOME指向的 JDK,如果 IDE 里配了别的,会出现命令行能编译、IDE 报错的玄学问题。2.2 Maven 版本与镜像配置Maven 用 3.8 以上即可,3.9 更稳。关键是settings.xml里配好镜像,否则拉 Spring Boot 3 的依赖会慢到怀疑人生。<!-- ~/.m2/settings.xml 片段 --> <mirrors> <mirror> <id>aliyun-central</id> <mirrorOf>central</mirrorOf> <name>aliyun central</name> <url>https://maven.aliyun.com/repository/central</url> </mirror> </mirrors>mirrorOf写central表示只代理中央仓库,不要写*,否则连公司私服也会被劫持。配完后执行mvn help:effective-settings确认镜像生效。2.3 版本对照表:别让 starter 版本打架Spring Boot 3 和 MyBatis-Plus 的版本必须成对选,下面是我验证过能跑通的组合:组件推荐版本说明JDK17 / 21LTS,21 性能更好Spring Boot3.2.x3.0/3.1 也可,3.2 最稳MyBatis-Plus3.5.5+必须用mybatis-plus-spring-boot3-starterMySQL 驱动8.0.33+用com.mysql.cj.jdbc.DriverLombok1.18.30+低版本在 JDK 21 下会编译失败最容易翻车的是 starter 名字:Spring Boot 3 要用mybatis-plus-spring-boot3-starter,不是老的mybatis-plus-boot-starter。用错了不会报错,只会扫描不到 Mapper。3. 依赖引入与 application.yml 配置落地3.1 pom.xml 里到底写哪几个依赖父工程锁定 Spring Boot 版本,子模块只引 starter,不要手动指定 MyBatis-Plus 的版本号,交给 BOM 管理。<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.5</version> <relativePath/> </parent> <dependencies> <!-- Web 基础,Spring Boot 3 自带 jakarta 命名空间 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 关键:Spring Boot 3 专用 starter,别用错 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.5</version> </dependency> <!-- MySQL 驱动,scope 用 runtime --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>mybatis-plus-spring-boot3-starter内部已经带了mybatis-spring和mybatis,不要再单独引mybatis-spring-boot-starter,两个一起引会导致自动配置冲突,启动时报BeanDefinitionOverrideException。3.2 application.yml 的最小可用配置spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/demo_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: your_password mybatis-plus: # Mapper XML 位置,多个路径用逗号分隔 mapper-locations: classpath*:/mapper/**/*.xml # 实体类别名包,XML 里可直接写类名 type-aliases-package: com.example.demo.entity configuration: # 下划线转驼峰,数据库 user_name -> 实体 userName map-underscore-to-camel-case: true # 开发期打印 SQL,上线关掉 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: # 主键自增,实体不写 @TableId 也能识别 id-type: automapper-locations里的classpath*:带星号,表示扫描所有 jar 和目录下的匹配文件,漏了星号在多模块项目里只能扫到当前模块。serverTimezone必须写,不写 MySQL 8 会报时区错误。3.3 启动类加 @MapperScan@SpringBootApplication @MapperScan("com.example.demo.mapper") // 扫描 Mapper 接口 public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }@MapperScan的包路径要精确到 mapper 接口所在包,不要写com.example.demo这种大范围,否则会把 Service 也当 Mapper 扫描,启动报No statement found。如果每个 Mapper 上都加了@Mapper,可以省略这个注解,但多模块下我建议统一用@MapperScan,省得漏。4. 分页插件与代码生成器:两个最容易配错的模块4.1 分页插件必须手动注册MyBatis-Plus 3.5.x 的分页插件不会自动生效,必须写配置类。不注册的话Page查询返回全部数据,total为 0,这是最高频的坑。@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 分页插件,指定数据库类型 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 乐观锁插件,按需加 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } }DbType.MYSQL要和你实际数据库一致,写成DbType.OTHER分页 SQL 会拼错。多个内部拦截器有顺序要求:分页插件放最后加,否则可能被其他拦截器改写 SQL 导致分页失效。4.2 分页查询的写法与验证// Service 层 public IPage<User> pageQuery(int pageNum, int pageSize) { Page<User> page = new Page<>(pageNum, pageSize); // 第二个参数是查询条件,null 表示查全部 return userMapper.selectPage(page, null); }Page的pageNum从 1 开始,不是 0。传 0 会返回空列表但不报错,很容易误判成没数据。验证时看控制台打印的 SQL 有没有LIMIT,有LIMIT且total正确,说明插件生效。4.3 代码生成器在 Spring Boot 3 下的调整MyBatis-Plus 的代码生成器依赖freemarker和velocity,Spring Boot 3 下要单独引,且模板引擎版本要新。FastAutoGenerator.create(url, username, password) .globalConfig(builder -> builder .author("dev") .outputDir(System.getProperty("user.dir") + "/src/main/java") .disableOpenDir()) // 生成后不自动打开目录 .packageConfig(builder -> builder .parent("com.example.demo") .entity("entity") .mapper("mapper") .service("service")) .strategyConfig(builder -> builder .addInclude("user", "order") // 指定表名 .entityBuilder().enableLombok()) .execute();outputDir用user.dir相对路径,别写死绝对路径,换机器就废。addInclude不写会生成全库所有表,生产库上跑一次能生成几百个文件。5. 避坑排查:整合后启动报错的五条血泪记录5.1 现象:Invalid bound statement (not found)原因:Mapper 接口和 XML 没对上。要么mapper-locations路径写错,要么 XML 的namespace不是接口全限定名,要么 XML 放在src/main/java下没配资源过滤。解决:先看target/classes/mapper下有没有 XML 文件,没有就是资源没打包。在pom.xml的<build>里加:<resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources>5.2 现象:分页 total 为 0,数据却查出来了原因:分页插件没注册,或者注册了但DbType写错。还有一种情况是自定义 SQL 里用了UNION,分页插件生成的 count 语句不兼容。解决:确认MybatisPlusInterceptor被 Spring 扫描到,自定义复杂 SQL 手动写 count 查询,用page.setTotal()设置。5.3 现象:启动报 jakarta.servlet 相关 ClassNotFound原因:引了老的javax.servlet依赖,或者某个第三方库还在用 javax。解决:mvn dependency:tree | grep javax.servlet找出冲突源,排除掉。Spring Boot 3 下所有 servlet 相关依赖都必须是 jakarta 版本。5.4 现象:Lombok 编译报错,提示找不到符号原因:Lombok 版本低于 1.18.30,在 JDK 21 下注解处理器不工作。解决:升级 Lombok 到 1.18.30+,并在maven-compiler-plugin里显式配置注解处理器路径。5.5 现象:多模块下子模块 Mapper 扫描不到原因:@MapperScan只写在启动类所在模块,子模块的 Mapper 包不在扫描范围。解决:@MapperScan写多个包路径,或者用@MapperScan(basePackages = {"com.example.module1.mapper", "com.example.module2.mapper"})。6. 装完怎么验证:三条命令确认整合真的跑通环境装完别急着写业务,先跑一遍验证。我一般按下面三步走,任何一步不过就回去查对应配置。第一步,启动应用看日志。控制台出现MyBatis-Plus的 banner 和Started DemoApplication才算启动成功。如果看到No MyBatis mapper was found的警告,说明@MapperScan路径不对。第二步,调一个分页接口,看控制台 SQL。正常应该打印两条:一条SELECT COUNT(*),一条带LIMIT的查询。只有一条带LIMIT的,说明分页插件没生效。# 用 curl 验证分页接口 curl "http://127.0.0.1:8080/user/page?pageNum=1&pageSize=10" # 期望返回:{"records":[...],"total":100,"size":10,"current":1}total是真实总数,records长度等于pageSize,current等于传入的pageNum,三个都对才算过。第三步,验证 XML 自定义 SQL。写一个带resultMap的查询,确认字段映射正确。如果返回对象字段全是 null,检查map-underscore-to-camel-case是否开启,以及 XML 里resultType写的是不是全限定名。验证项通过标准失败先查应用启动无 Mapper 警告@MapperScan 路径分页查询有 COUNT 和 LIMIT分页插件注册XML 查询字段有值mapper-locations主键回填insert 后 id 有值id-type 配置从那以后我每次搭 Spring Boot 3 加 MyBatis-Plus 的环境,都强制先跑这三步再写业务代码,省得写到一半发现分页是坏的、字段映射是错的,回头返工更费时间。希望帮到你。本文还有配套的精品资源,点击获取