1. MyBatis-Plus核心注解全景解析
作为MyBatis的增强工具,MyBatis-Plus通过一系列注解极大地简化了数据库操作。这些注解主要分为五大类:
- 表结构映射注解:建立Java对象与数据库表的对应关系
- 字段映射注解:处理字段与列的特殊映射需求
- 功能控制注解:实现特定功能如乐观锁、逻辑删除
- 插件控制注解:管理插件拦截行为
- 辅助功能注解:提供排序等附加功能
在实际项目中,合理使用这些注解可以减少约60%的传统MyBatis XML配置工作量。下面我们通过具体案例来剖析每个注解的实战用法。
2. 表结构映射注解深度应用
2.1 @TableName实战详解
@TableName是MyBatis-Plus中最基础的注解,用于建立实体类与数据库表的映射关系。考虑以下电商系统中的商品实体:
java复制@TableName(value = "t_product", schema = "ecommerce",
keepGlobalPrefix = true, autoResultMap = true)
public class Product {
// 类字段定义
}
关键属性解析:
- value:当表名与类名不符合驼峰转下划线规则时必须指定
- schema:在分库场景下指定数据库schema(MySQL中相当于database)
- keepGlobalPrefix:与全局配置的tablePrefix配合使用,实现统一表前缀
- autoResultMap:自动构建resultMap,特别处理typeHandler字段
踩坑提示:当使用autoResultMap=true时,查询操作必须使用selectById等MP内置方法,自定义SQL不会自动应用resultMap。
2.2 @TableId主键策略剖析
主键策略是数据库设计的关键考量,MyBatis-Plus提供了多种内置策略:
java复制@TableId(value = "product_id", type = IdType.ASSIGN_ID)
private Long id;
主键类型对比:
| 策略类型 | 适用场景 | 实现原理 | 优缺点 |
|---|---|---|---|
| AUTO | 数据库自增 | 依赖数据库自增 | 简单但分库分表有问题 |
| ASSIGN_ID | 分布式系统 | 雪花算法 | 无序但全局唯一 |
| ASSIGN_UUID | 需要字符串ID | UUID生成 | 存储空间大查询慢 |
| INPUT | 自定义ID | 用户手动设置 | 最灵活但需保证唯一性 |
项目经验:在微服务架构中,ASSIGN_ID是首选方案。我们曾在订单系统从AUTO切换到ASSIGN_ID,解决了分库后的ID冲突问题。
3. 字段映射与策略控制
3.1 @TableField高级用法
@TableField是使用频率最高的注解之一,其丰富属性可以应对各种复杂场景:
java复制@TableField(value = "product_name",
condition = SqlCondition.LIKE,
updateStrategy = FieldStrategy.NOT_EMPTY,
fill = FieldFill.INSERT_UPDATE,
typeHandler = JsonTypeHandler.class)
private String name;
条件构造技巧:
- condition属性支持SQL片段模板,如"price > #{price}"
- 配合QueryWrapper可实现动态条件:
java复制queryWrapper.lt(Product::getPrice, 100) .like(Product::getName, "手机");
字段策略实战:
- insertStrategy/updateStrategy控制字段在CRUD中的行为
- 敏感字段建议设置select=false防止泄露
- 使用typeHandler处理JSON等复杂类型
3.2 自动填充字段实现
创建时间、更新时间等字段可以通过自动填充减少重复代码:
java复制@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
需要配置元对象处理器:
java复制@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
4. 高级功能注解实战
4.1 乐观锁实现并发控制
电商库存管理典型场景:
java复制@Version
private Integer version;
配置乐观锁插件:
java复制@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
使用模式:
java复制// 查询时获取version
Product product = productMapper.selectById(1L);
// 修改数据
product.setStock(product.getStock() - 1);
// 更新时检查version
productMapper.updateById(product);
4.2 逻辑删除优雅实现数据隔离
java复制@TableLogic(value = "0", delval = "1")
private Integer deleted;
配置删除插件:
java复制@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
注意事项:
- 查询会自动过滤deleted=1的记录
- 删除操作变为update语句
- 需要数据库字段默认值为0
4.3 枚举类型优雅处理
订单状态枚举示例:
java复制public enum OrderStatus {
@EnumValue
PAID(1, "已支付"),
SHIPPED(2, "已发货");
private final int code;
private final String desc;
// 构造方法等
}
配置枚举处理器:
java复制mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
5. 注解组合使用最佳实践
5.1 多租户系统注解配置
java复制@TableName("t_order")
@InterceptorIgnore(tenantLine = "true") // 忽略租户过滤
public class Order {
@TableField(exist = false)
private List<OrderItem> items;
}
多租户配置示例:
java复制public class MyTenantLineHandler implements TenantLineHandler {
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public Expression getTenantId() {
return new StringValue("当前租户ID");
}
@Override
public boolean ignoreTable(String tableName) {
return !"t_order".equals(tableName);
}
}
5.2 复杂查询场景优化
java复制public interface ProductMapper extends BaseMapper<Product> {
@InterceptorIgnore(illegalSql = "true") // 允许复杂SQL
@Select("SELECT * FROM t_product WHERE price > #{price} ORDER BY ${orderBy}")
List<Product> selectExpensiveProducts(@Param("price") BigDecimal price,
@Param("orderBy") String orderBy);
}
性能优化建议:
- 大数据量查询使用@OrderBy指定默认排序
- 敏感操作使用@InterceptorIgnore关闭插件拦截
- 复杂SQL配合@Select注解使用
6. 注解原理与扩展机制
6.1 注解处理流程解析
MyBatis-Plus通过以下流程处理注解:
- 启动时扫描实体类注解
- 构建SQL元信息(TableInfo、FieldInfo)
- 注册自定义TypeHandler
- 初始化插件拦截器链
- 运行时动态应用注解规则
6.2 自定义注解开发
开发自定义ID生成注解示例:
java复制@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CustomId {
String prefix() default "";
}
实现自定义ID生成器:
java复制public class CustomIdGenerator implements IdentifierGenerator {
@Override
public Number nextId(Object entity) {
// 解析CustomId注解生成ID
}
}
配置自定义生成器:
java复制@Bean
public IdentifierGenerator idGenerator() {
return new CustomIdGenerator();
}
通过深入理解MyBatis-Plus注解机制,开发者可以大幅提升持久层开发效率,构建更健壮的数据访问层。建议根据实际项目需求,合理组合使用各类注解,同时注意避免过度依赖注解导致的代码可读性下降问题。
