1. 环境准备与项目初始化
在开始整合Spring Boot和MyBatis-Plus之前,我们需要先搭建好开发环境。我推荐使用以下工具和版本,这也是经过我多次实践验证的稳定组合:
- JDK 17:目前LTS版本,性能稳定且支持新特性
- IntelliJ IDEA 2022.3+:社区版或旗舰版均可
- Maven 3.6.3+:构建工具
- MySQL 8.0+:数据库服务
首先打开IDEA,创建一个新的Maven项目。这里有个小技巧:先创建一个空的父项目,再添加子模块。这样做的好处是:
- 可以统一管理依赖版本
- 便于后续扩展多模块
- 符合企业级项目结构规范
创建完成后,项目结构应该如下:
elephant-demo (父项目) ├── pom.xml └── demo-service (子模块) ├── src │ ├── main │ │ ├── java │ │ └── resources │ └── test └── pom.xml2. 关键依赖配置
2.1 父POM配置
在父项目的pom.xml中,我们需要定义Spring Boot的父POM和版本管理。这里有个重要经验:不要盲目使用最新版本!我最初用Spring Boot 3.0就踩了不少坑,最终选择了稳定的2.6.13版本。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.13</version> <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>17</java.version> <mybatis-plus.version>3.5.2</mybatis-plus.version> <mysql.version>8.0.31</mysql.version> </properties>2.2 子模块基础依赖
在demo-service模块的pom.xml中,添加以下核心依赖:
<dependencies> <!-- Spring Boot基础 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 健康检查(排查问题必备) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- MyBatis-Plus核心 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> </dependencies>3. 数据库配置与实体映射
3.1 数据库连接配置
在application.yml中配置数据库连接,这里有几个关键点需要注意:
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456 hikari: maximum-pool-size: 20 # 连接池大小根据实际情况调整 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开发时开启SQL日志 map-underscore-to-camel-case: true # 自动驼峰转换 type-aliases-package: com.example.demo.entity # 实体类包路径特别注意:MySQL 8.0+必须指定时区,否则会报时区错误。生产环境记得关闭SQL日志输出。
3.2 实体类设计
创建一个简单的订单实体类,演示MyBatis-Plus的注解使用:
@Data @TableName("ft_order") // 指定表名 public class Order { @TableId(type = IdType.ASSIGN_ID) // 分布式ID private String id; private String orderNo; private String customerName; private String customerEmail; @TableField(fill = FieldFill.INSERT) // 自动填充 private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; @TableLogic // 逻辑删除标记 private Integer isDeleted; }4. 核心功能实现
4.1 Mapper接口与XML配置
MyBatis-Plus的Mapper接口只需要继承BaseMapper即可获得CRUD方法:
public interface OrderMapper extends BaseMapper<Order> { // 自定义分页查询 IPage<Order> selectOrderPage(Page<Order> page, @Param("param") Map<String, Object> param); }对应的XML映射文件(resources/mapper/OrderMapper.xml):
<mapper namespace="com.example.demo.mapper.OrderMapper"> <select id="selectOrderPage" resultType="com.example.demo.entity.Order"> SELECT * FROM ft_order <where> is_deleted = 0 <if test="param.orderNo != null"> AND order_no LIKE CONCAT('%', #{param.orderNo}, '%') </if> </where> </select> </mapper>4.2 Service层实现
Service层可以继承ServiceImpl获得基础CRUD能力:
public interface OrderService extends IService<Order> { PageResult<Order> pageQuery(OrderQuery query); } @Service public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService { @Override public PageResult<Order> pageQuery(OrderQuery query) { Page<Order> page = new Page<>(query.getPageNum(), query.getPageSize()); Map<String, Object> params = new HashMap<>(); params.put("orderNo", query.getOrderNo()); IPage<Order> result = baseMapper.selectOrderPage(page, params); return new PageResult<>(result.getRecords(), result.getTotal()); } }5. 高级功能与最佳实践
5.1 自动填充处理
实现MetaObjectHandler接口来处理创建时间和更新时间:
@Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); this.strictInsertFill(metaObject, "updateTime", Date.class, new Date()); } @Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); } }5.2 分页插件配置
必须配置分页插件才能使用IPage:
@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }5.3 逻辑删除配置
在application.yml中配置逻辑删除:
mybatis-plus: global-config: db-config: logic-delete-field: isDeleted # 逻辑删除字段名 logic-delete-value: 1 # 删除值 logic-not-delete-value: 0 # 未删除值6. 常见问题排查
6.1 启动时报错找不到Mapper
这个问题通常有两个原因:
- 没有在启动类添加@MapperScan注解
- Mapper.xml文件没有放在正确位置
解决方案:
@SpringBootApplication @MapperScan("com.example.demo.mapper") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }6.2 SQL执行报错
如果遇到SQL语法错误,可以:
- 检查application.yml中的SQL日志是否开启
- 复制控制台输出的SQL到数据库客户端执行
- 检查实体类字段名与数据库列名是否匹配
6.3 事务不生效
确保:
- 方法上有@Transactional注解
- 抛出的异常是RuntimeException
- 不要在同一个类中调用事务方法
7. 项目优化建议
- 多数据源配置:使用dynamic-datasource-spring-boot-starter
- 性能监控:集成Prometheus监控SQL性能
- 代码生成器:利用MyBatis-Plus的代码生成器自动生成基础代码
- 二级缓存:合理使用Redis作为MyBatis二级缓存
我在实际项目中发现,合理的索引设计和避免N+1查询问题可以大幅提升性能。对于复杂查询,建议使用QueryWrapper构建动态查询条件,而不是拼接SQL字符串。