MyBatis-Plus 插件
MyBatis-Plus(简称 MP)是基于 MyBatis 的增强工具,在保留原生功能的基础上,提供了简化开发、自动 CRUD、分页、代码生成等特性。以下从核心功能、插件模块及使用示例展开说明。
核心功能
代码生成器
通过AutoGenerator可快速生成 Entity、Mapper、Service、Controller 层代码,支持自定义模板。
条件构造器
提供QueryWrapper和UpdateWrapper,通过链式调用构建动态 SQL 条件,无需手动拼接 SQL。
分页插件
内置PaginationInnerInterceptor,支持多种数据库分页逻辑,与Page对象配合实现物理分页。
乐观锁插件
通过@Version注解标记版本号字段,自动实现乐观锁控制。
性能分析插件PerformanceInterceptor可输出 SQL 执行时间,帮助优化慢查询。
常用插件配置示例
分页插件配置
在 Spring Boot 中配置分页插件:
@Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }代码生成器示例
AutoGenerator generator = new AutoGenerator(); generator.setDataSource(new DataSourceConfig() .setUrl("jdbc:mysql://localhost:3306/test") .setUsername("root") .setPassword("123456")); StrategyConfig strategy = new StrategyConfig() .setInclude("user", "order") // 指定生成表 .setEntityLombokModel(true); // 使用 Lombok generator.setStrategy(strategy); generator.execute();动态表名插件
适用于分库分表场景,通过实现TableNameHandler动态解析表名:
public class DynamicTableNameParser implements TableNameHandler { @Override public String dynamicTableName(String sql, String tableName) { return tableName + "_2023"; // 动态拼接表名 } }注意事项
- 避免在 Wrapper 中直接拼接用户输入,防止 SQL 注入。
- 分页插件需依赖数据库方言(如
DbType.MYSQL)。 - 乐观锁字段需为数值类型,且更新时自动递增版本号。
通过合理使用插件,可显著减少样板代码,提升开发效率。
mybatis-Plus扩展功能
逻辑删除
逻辑删除是一种软删除方式,通过标记字段(如is_deleted)的状态区分数据是否被删除,而非物理删除数据库记录。MyBatis-Plus提供了内置支持,简化逻辑删除的实现。
配置逻辑删除字段
在实体类中标记逻辑删除字段,使用@TableLogic注解:
@Data public class User { private Long id; private String name; @TableLogic private Integer isDeleted; // 1表示删除,0表示未删除 }全局配置(可选)
在application.yml中配置逻辑删除的默认值,避免在每个实体类中重复定义:
mybatis-plus: global-config: db-config: logic-delete-field: isDeleted # 全局逻辑删除字段名 logic-not-delete-value: 0 # 未删除时的值 logic-delete-value: 1 # 删除时的值自动过滤逻辑删除数据
MyBatis-Plus会在查询时自动过滤标记为已删除的数据,无需手动添加条件。例如:
userMapper.selectList(null); // 自动生成SQL: WHERE is_deleted = 0手动调用删除方法
使用deleteById或delete方法会触发逻辑删除:
userMapper.deleteById(1L); // 执行UPDATE语句,设置is_deleted = 1查询包含已删除数据
若需查询包含逻辑删除的数据,需自定义SQL或使用条件构造器忽略逻辑删除字段:
QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.isNull("is_deleted").or().eq("is_deleted", 1); userMapper.selectList(wrapper);注意事项
- 数据库表需存在逻辑删除字段(如
is_deleted)。 - 逻辑删除与唯一索引冲突时,需调整业务逻辑或索引设计。
- 关联查询时需手动处理逻辑删除条件。
通过上述配置,MyBatis-Plus可无缝集成逻辑删除功能,减少冗余代码。
自动填充功能
MyBatis-Plus的自动填充功能用于在数据库操作时自动填充字段值,例如创建时间、更新时间、操作人等。通过实现MetaObjectHandler接口,可以自定义填充逻辑。
实现自动填充的步骤
定义填充字段注解
在实体类字段上使用@TableField注解标记自动填充行为,例如:
@TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime;FieldFill.INSERT:仅在插入时填充FieldFill.UPDATE:仅在更新时填充FieldFill.INSERT_UPDATE:插入和更新时均填充
实现MetaObjectHandler接口
创建类实现MetaObjectHandler,重写insertFill和updateFill方法:
@Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); } @Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); } }strictInsertFill/strictUpdateFill:严格模式填充,要求字段类型匹配- 非严格模式可使用
setFieldValByName方法
注意事项
- 字段类型需与填充值类型一致,否则会抛出异常。
- 填充字段需在数据库中存在,且为非主键字段。
- 若填充逻辑依赖其他服务(如获取当前用户),可通过Spring上下文注入依赖。
高级用法
动态填充
通过MetaObject获取当前操作数据,实现条件填充:
@Override public void insertFill(MetaObject metaObject) { Object status = metaObject.getValue("status"); if ("draft".equals(status)) { this.setFieldValByName("publishTime", null, metaObject); } else { this.setFieldValByName("publishTime", LocalDateTime.now(), metaObject); } }多数据源适配
在多数据源场景下,需确保MetaObjectHandler实现类被所有数据源识别,通常将其声明为Spring Bean即可自动生效。
常见问题解决
- 填充不生效:检查字段注解
fill值是否与操作类型匹配,或是否漏注@Component。 - 类型不匹配错误:使用
strictFill方法时,确认填充值与字段类型一致。 - 覆盖问题:手动设置的字段值会优先于自动填充值。
SpringBoot集成Druid数据源
Druid 概述
Druid 是一个开源的分布式实时数据分析系统,专为快速查询和实时摄入大规模数据而设计。它结合了数据仓库、时序数据库和搜索系统的特性,适用于高性能的 OLAP(在线分析处理)场景。
核心特性
- 实时与批量摄入:支持从 Kafka 等流式数据源实时摄入数据,也支持批量导入历史数据。
- 列式存储:数据按列存储,优化聚合和扫描性能。
- 分布式架构:通过横向扩展处理 PB 级数据,支持高可用和容错。
- 时间分区:数据按时间分片,便于高效查询和时间范围过滤。
- 近似计算:提供 HyperLogLog 等算法,支持快速去重和近似计算。
适用场景
- 实时监控与日志分析
- 用户行为分析
- 广告技术(AdTech)中的点击流分析
- IoT 设备数据时序分析
架构组件
- Coordinator:管理数据分片的分布和负载均衡。
- Overlord:控制数据摄入任务的分配。
- Broker:接收查询请求并路由到数据节点。
- Historical:存储和提供历史数据查询。
- MiddleManager:处理实时数据摄入。
查询能力
- 支持 SQL 和原生 JSON 查询。
- 提供聚合、过滤、分组、排序等操作。
- 低延迟响应,适用于交互式分析。
与其他工具的对比
- 对比 Elasticsearch:Druid 更擅长聚合分析,Elasticsearch 侧重全文检索。
- 对比 Hadoop:Druid 提供亚秒级查询,Hadoop 更适合离线批处理。
部署方式
- 可独立部署或集成 Kubernetes 等容器化平台。
- 社区版开源,企业版提供额外功能和支持。
Druid 的官方文档和社区资源丰富,适合需要高性能实时分析的企业级应用。
依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-3-starter</artifactId> <version>1.2.23</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>application.yml相关配置
# 服务器配置(核心修正:端口key) server: port: 8080 servlet: context-path: / # 上下文路径(默认/,可省略) # Spring 核心配置 spring: application: name: mybatis-xml # 数据源配置(Druid) datasource: type: com.alibaba.druid.pool.DruidDataSource druid: # 数据库连接信息(适配MySQL 8.x) url: jdbc:mysql://localhost:3306/text_book_db?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver # 连接池核心参数 initial-size: 5 min-idle: 5 max-active: 20 max-wait: 60000 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 validation-query: SELECT 1 FROM DUAL test-while-idle: true test-on-borrow: false test-on-return: false # PreparedStatement 缓存 pool-prepared-statements: true max-pool-prepared-statement-per-connection-size: 20 # 过滤器(stat=SQL监控,wall=防注入,slf4j=日志) filters: stat,wall,slf4j # 修正:connection-properties 改用行内写法,避免解析失败 connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000;druid.stat.logSlowSql=true # Druid 监控页面配置 stat-view-servlet: enabled: true url-pattern: /druid/* login-username: admin login-password: admin123 reset-enable: false allow: 127.0.0.1 # 仅允许本地访问(生产按需扩展) deny: 192.168.1.100 # Web 请求监控过滤器 web-stat-filter: enabled: true url-pattern: /* exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" session-stat-enable: true session-stat-max-count: 1000 principal-session-name: loginUser principal-cookie-name: loginUser # MyBatis-Plus 配置(适配XML开发) mybatis-plus: type-aliases-package: com.ktjy.crm.entity mapper-locations: classpath:generator/mapper/**/*.xml # 确保XML文件在该路径下 configuration: map-underscore-to-camel-case: true # 下划线转驼峰(必须开) cache-enabled: false call-setters-on-nulls: true # 空值字段返回(前端不缺字段) log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl # 打印SQL到日志 global-config: db-config: # 关键修正:根据数据库主键策略调整(二选一) # 若主键自增(AUTO_INCREMENT),用这个: id-type: auto # 若主键是雪花算法(手动生成),用这个: # id-type: assign_id update-strategy: not_null logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0 # 日志配置(打印SQL和Druid日志) logging: level: root: WARN com.ktjy.crm.mapper: DEBUG # 打印Mapper执行的SQL(关键调试) com.alibaba.druid: INFO # Druid监控日志 com.baomidou.mybatisplus: INFO # MyBatis-Plus日志 pattern: console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n"