MyBatis-Plus 配置
通过 MybatisPlusConfigHandler 自动注册分页拦截器与默认 ID 生成器
MyBatis-Plus 配置
bamboo-mvc 不直接定义分页配置类,而是在自动配置中注册
com.xlf.utility.app.config.MybatisPlusConfigHandler(来自 bamboo-base)。
自动注册入口
@Bean
@ConditionalOnMissingBean
@ConditionalOnClass(name = "com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor")
public MybatisPlusConfigHandler mybatisPlusConfigHandler(UtilityBaseProperties properties) {
return new MybatisPlusConfigHandler(properties);
}MybatisPlusConfigHandler 提供的能力
- 注册
MybatisPlusInterceptor+PaginationInnerInterceptor - 从
UtilityBaseProperties读取数据库类型和分页上限 - 注册
MybatisPlusPropertiesCustomizer,默认使用OrdinaryGenerator
配置项
bamboo:
base:
datasource:
db-type: MYSQL
page:
max-limit: 500
default-limit: 20字段
类型
使用示例
public IPage<UserEntity> getUserList(int current, int size) {
Page<UserEntity> page = new Page<>(current, size);
return userMapper.selectPage(page, null);
}扩展配置
业务项目可以继承 MybatisPlusConfigHandler 并实现 MetaObjectHandler 接口,
以扩展乐观锁、自定义 ID 生成器和元数据自动填充功能。
乐观锁插件
通过重写 mybatisPlusInterceptor() 方法,在父类分页拦截器的基础上添加乐观锁插件:
@Override
public MybatisPlusInterceptor mybatisPlusInterceptor() {
return Optional.of(super.mybatisPlusInterceptor())
.map(interceptor -> {
// 添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
})
.orElseThrow(() -> new ServerInternalErrorException("初始化 MybatisPlusInterceptor 失败"));
}在实体类中使用 @Version 注解标识乐观锁字段:
@Data
@TableName("t_user")
public class UserEntity {
@Version
private Long version;
// 其他字段...
}字段
类型
乐观锁工作原理
- 更新时 MyBatis-Plus 自动在 WHERE 条件中添加
version = 旧值 - 同时 SET 中自动
version = 旧值 + 1 - 如果受影响行数为 0,说明被其他事务修改过
自定义 ID 生成器
默认使用 OrdinaryGenerator 生成 ID(生成6位随机整数),可以通过重写 plusPropertiesCustomizer() 方法替换为雪花算法:
默认 ID 生成器
默认使用 OrdinaryGenerator,生成6位随机整数。如需分布式唯一 ID,建议替换为 SnowflakeIdGenerator。
@Override
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
return mybatisProperties -> mybatisProperties.getGlobalConfig()
.setIdentifierGenerator(new SnowflakeIdGenerator(
properties.getSnowflake().getDatacenterId(),
properties.getSnowflake().getMachineId(),
properties.getSnowflake().getEpoch()
));
}字段
类型
雪花算法 ID 结构
SnowflakeIdGenerator 生成64位长整型 ID,结构如下:
┌─────────────┬──────────┬──────────┬─────────────┐
│ 时间戳位 │ 数据中心 │ 机器ID位 │ 序列号位 │
│ (41位) │ (5位) │ (5位) │ (12位) │
└─────────────┴──────────┴──────────┴─────────────┘
63 22 21 17 16 12 11 0- 时间戳位:41位,可支持约69年的时间范围
- 数据中心位:5位,支持32个数据中心
- 机器ID位:5位,每个数据中心支持32台机器
- 序列号位:12位,每毫秒可生成4096个ID
元数据自动填充
实现 MetaObjectHandler 接口,在插入和更新时自动填充公共字段:
@Slf4j
@Configuration
public class MybatisPlusConfig extends MybatisPlusConfigHandler implements MetaObjectHandler {
public MybatisPlusConfig(UtilityBaseProperties properties) {
super(properties);
}
@Override
public void insertFill(@NotNull MetaObject metaObject) {
log.debug("自定义插入填充 {}", metaObject.getOriginalObject().getClass().getName());
this.strictInsertFill(metaObject, "createdAt", Timestamp.class, new Timestamp(System.currentTimeMillis()));
this.strictInsertFill(metaObject, "updatedAt", Timestamp.class, new Timestamp(System.currentTimeMillis()));
this.strictInsertFill(metaObject, "version", Long.class, 0L);
this.strictInsertFill(metaObject, "delete", Boolean.class, false);
}
@Override
public void updateFill(@NotNull MetaObject metaObject) {
log.debug("自定义更新填充 {}", metaObject.getOriginalObject().getClass().getName());
this.strictUpdateFill(metaObject, "updatedAt", Timestamp.class, new Timestamp(System.currentTimeMillis()));
this.strictUpdateFill(metaObject, "delete", Boolean.class, false);
}
}自动填充字段规则
| 字段 | 插入时填充 | 更新时填充 | 类型 | 默认值 |
|---|---|---|---|---|
createdAt | ✅ | ❌ | Timestamp | 当前时间 |
updatedAt | ✅ | ✅ | Timestamp | 当前时间 |
version | ✅ | ❌ | Long | 0L |
delete | ✅ | ✅ | Boolean | false |
严格填充模式
使用 strictInsertFill / strictUpdateFill 进行严格填充,仅在字段为 null 时才会填充值。
如果字段已有值,则不会覆盖。这样可以保护业务代码中手动设置的值。
实体类注解配置
在实体类中使用 @TableField 注解指定字段的填充策略:
@Data
@TableName("t_user")
public class UserEntity {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String username;
@TableField(fill = FieldFill.INSERT)
private Timestamp createdAt;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Timestamp updatedAt;
@Version
private Long version;
@TableLogic
@TableField(fill = FieldFill.INSERT_UPDATE)
private Boolean delete;
}字段
类型
完整配置示例
以下是一个完整的 MyBatis-Plus 扩展配置类,集成了乐观锁、雪花算法 ID 生成器和元数据自动填充:
@Slf4j
@Configuration
public class MybatisPlusConfig extends MybatisPlusConfigHandler implements MetaObjectHandler {
public MybatisPlusConfig(UtilityBaseProperties properties) {
super(properties);
}
@Override
public MybatisPlusInterceptor mybatisPlusInterceptor() {
return Optional.of(super.mybatisPlusInterceptor())
.map(interceptor -> {
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
})
.orElseThrow(() -> new ServerInternalErrorException("初始化 MybatisPlusInterceptor 失败"));
}
@Override
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
return mybatisProperties -> mybatisProperties.getGlobalConfig()
.setIdentifierGenerator(new SnowflakeIdGenerator(
properties.getSnowflake().getDatacenterId(),
properties.getSnowflake().getMachineId(),
properties.getSnowflake().getEpoch()
));
}
@Override
public void insertFill(@NotNull MetaObject metaObject) {
log.debug("自定义插入填充 {}", metaObject.getOriginalObject().getClass().getName());
this.strictInsertFill(metaObject, "createdAt", Timestamp.class, new Timestamp(System.currentTimeMillis()));
this.strictInsertFill(metaObject, "updatedAt", Timestamp.class, new Timestamp(System.currentTimeMillis()));
this.strictInsertFill(metaObject, "version", Long.class, 0L);
this.strictInsertFill(metaObject, "delete", Boolean.class, false);
}
@Override
public void updateFill(@NotNull MetaObject metaObject) {
log.debug("自定义更新填充 {}", metaObject.getOriginalObject().getClass().getName());
this.strictUpdateFill(metaObject, "updatedAt", Timestamp.class, new Timestamp(System.currentTimeMillis()));
this.strictUpdateFill(metaObject, "delete", Boolean.class, false);
}
}注意事项
- 未引入 MyBatis-Plus 时,该 Bean 不会注册。
- 分页能力来自
bamboo-base,mvc与webflux共用同一套配置实现。 - 乐观锁插件仅支持
Integer、Long、Date、Timestamp类型的版本字段。 - 自定义配置类需要继承
MybatisPlusConfigHandler并添加@Configuration注解。