一、基础配置与实现
1.1 实体类字段注解配置
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.util.Date;
@Data
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String username;
// 插入时自动填充当前时间
@TableField(fill = FieldFill.INSERT)
private Date createTime;
// 插入和更新时自动填充当前时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
// 逻辑删除字段(删除时自动填充当前时间)
@TableLogic
@TableField(fill = FieldFill.UPDATE)
private Date deleteTime;
}
![图片[1]_MyBatis-Plus 日期时间自动填充实践指南_知途无界](https://zhituwujie.com/wp-content/uploads/2025/09/d2b5ca33bd20250910090951.png)
1.2 元对象处理器实现
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@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());
}
}
二、高级配置与优化
2.1 多种日期格式支持
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
// 使用Java8的日期时间API
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
// 支持时间戳格式
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", Long.class, System.currentTimeMillis());
}
}
2.2 条件填充控制
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 只有特定表才填充
if (metaObject.getOriginalObject() instanceof User) {
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
}
// 根据字段值决定是否填充
Object status = metaObject.getValue("status");
if (status != null && (Integer)status == 1) {
this.strictInsertFill(metaObject, "activeTime", Date.class, new Date());
}
}
}
三、多场景实践方案
3.1 审计字段完整配置
@Data
public class BaseEntity {
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
// 在处理器中获取当前用户信息
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Autowired
private CurrentUserService userService;
@Override
public void insertFill(MetaObject metaObject) {
Long userId = userService.getCurrentUserId();
this.strictInsertFill(metaObject, "createBy", Long.class, userId);
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
}
@Override
public void updateFill(MetaObject metaObject) {
Long userId = userService.getCurrentUserId();
this.strictUpdateFill(metaObject, "updateBy", Long.class, userId);
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
}
}
3.2 多租户场景下的时间填充
@Component
public class TenantMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 填充租户ID和时间
this.strictInsertFill(metaObject, "tenantId", String.class, TenantContext.getCurrentTenant());
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
}
@Override
public void updateFill(MetaObject metaObject) {
// 只更新时间字段
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
}
}
四、常见问题解决方案
4.1 时区问题处理
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
private Date getCurrentTime() {
// 设置时区为东八区
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
return new Date();
}
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", Date.class, getCurrentTime());
}
}
4.2 字段未自动填充排查
- 检查项:
- 实体类字段是否有
@TableField(fill = ...)注解 - 处理器类是否有
@Component注解 - 字段名称是否与处理器中一致
- 字段类型是否匹配
- 实体类字段是否有
- 调试方法:
@Override public void insertFill(MetaObject metaObject) { System.out.println("Insert fill triggered for: " + metaObject.getOriginalObject().getClass().getName()); this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); }
五、性能优化建议
5.1 批量插入优化
@Component
public class BatchInsertMetaObjectHandler implements MetaObjectHandler {
private ThreadLocal<Date> batchTime = new ThreadLocal<>();
public void startBatch() {
batchTime.set(new Date());
}
public void endBatch() {
batchTime.remove();
}
@Override
public void insertFill(MetaObject metaObject) {
Date now = batchTime.get() != null ? batchTime.get() : new Date();
this.strictInsertFill(metaObject, "createTime", Date.class, now);
}
}
// 使用示例
public void batchInsert(List<User> users) {
try {
metaObjectHandler.startBatch();
userService.saveBatch(users);
} finally {
metaObjectHandler.endBatch();
}
}
5.2 缓存时间对象
@Component
public class CachedTimeMetaObjectHandler implements MetaObjectHandler {
private volatile long lastTimestamp = 0;
private volatile Date cachedDate = null;
private Date getCachedDate() {
long now = System.currentTimeMillis();
if (now - lastTimestamp > 1000) { // 1秒缓存
lastTimestamp = now;
cachedDate = new Date(now);
}
return cachedDate;
}
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", Date.class, getCachedDate());
}
}
六、Spring Boot 完整配置示例
6.1 完整配置类
@Configuration
@EnableTransactionManagement
@MapperScan("com.example.mapper")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean
public MetaObjectHandler metaObjectHandler() {
return new MyMetaObjectHandler();
}
}
6.2 完整处理器实现
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
private static final Logger logger = LoggerFactory.getLogger(MyMetaObjectHandler.class);
@Override
public void insertFill(MetaObject metaObject) {
logger.debug("Start insert fill...");
try {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
// 获取当前用户
Long userId = getCurrentUserId();
if (userId != null) {
this.strictInsertFill(metaObject, "createBy", Long.class, userId);
}
} catch (Exception e) {
logger.error("Auto fill failed during insert", e);
}
}
@Override
public void updateFill(MetaObject metaObject) {
logger.debug("Start update fill...");
try {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
// 获取当前用户
Long userId = getCurrentUserId();
if (userId != null) {
this.strictUpdateFill(metaObject, "updateBy", Long.class, userId);
}
} catch (Exception e) {
logger.error("Auto fill failed during update", e);
}
}
private Long getCurrentUserId() {
// 实现获取当前用户ID的逻辑
try {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.getPrincipal() instanceof UserDetails) {
return ((CustomUserDetails) authentication.getPrincipal()).getUserId();
}
} catch (Exception e) {
logger.warn("Get current user id failed", e);
}
return null;
}
}
七、版本兼容性说明
| MyBatis-Plus 版本 | 特性变化 |
|---|---|
| 3.0.x | 基础自动填充功能 |
| 3.1.0+ | 添加strictInsertFill/strictUpdateFill方法 |
| 3.4.0+ | 支持LocalDateTime等Java8时间API |
| 3.5.0+ | 优化填充逻辑,支持更多场景 |
最佳实践建议:
- 对于新项目,建议使用最新的MyBatis-Plus版本(≥3.5.0)
- 生产环境建议使用Java8时间API(LocalDateTime)
- 审计字段(创建人、更新时间等)建议统一放在基类中
- 对于批量操作,考虑使用缓存时间提升性能
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END

























暂无评论内容