目录
1. 使用 MyBatis 拦截器实现字段自动填充
2. 使用 MyBatis-Plus 实现字段自动填充
1. 使用 MyBatis 拦截器实现字段自动填充
实现步骤
-
创建拦截器 实现 MyBatis 的
Interceptor
接口,通过拦截 MyBatis 执行的 SQL 操作来自动填充公共字段@Intercepts({ @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}) }) public class CommonFieldInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { if (invocation.getArgs().length > 1) { Object parameter = invocation.getArgs()[1]; if (parameter instanceof BaseEntity) { BaseEntity entity = (BaseEntity) parameter; if (isInsertOperation(invocation)) { entity.setCreateTime(new Date()); entity.setUpdateTime(new Date()); } else if (isUpdateOperation(invocation)) { entity.setUpdateTime(new Date()); } } } return invocation.proceed(); } private boolean isInsertOperation(Invocation invocation) { String methodName = ((MappedStatement) invocation.getArgs()[0]).getId(); return methodName.contains("insert"); } private boolean isUpdateOperation(Invocation invocation) { String methodName = ((MappedStatement) invocation.getArgs()[0]).getId(); return methodName.contains("update"); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // 可选:设置属性 } }
-
定义基础实体类 创建一个基础实体类
BaseEntity
,包含需要自动填充的公共字段,所有需要自动填充的实体类都应继承该类public class BaseEntity { private Date createTime; private Date updateTime; // getters and setters public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } }
-
配置拦截器 在 MyBatis 配置文件中注册拦截器
<plugins> <plugin interceptor="com.example.mybatis.interceptor.CommonFieldInterceptor"/> </plugins>
-
使用示例 创建一个继承
BaseEntity
的实体类,并在 Mapper 中使用该实体类进行数据库操作public class User extends BaseEntity { private Long id; private String name; // getters and setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
@Mapper public interface UserMapper { @Insert("INSERT INTO user (name, create_time, update_time) VALUES (#{name}, #{createTime}, #{updateTime})") void insert(User user); @Update("UPDATE user SET name = #{name}, update_time = #{updateTime} WHERE id = #{id}") void update(User user); }
2. 使用 MyBatis-Plus 实现字段自动填充
实现步骤
-
定义实体类 在实体类中,使用
@TableField
注解来标记需要自动填充的字段,并指定填充策略@Data @TableName("user") public class User { @TableId(type = IdType.AUTO) private Integer id; private String username; @TableField(fill = FieldFill.INSERT) private LocalDateTime createdAt; // 创建时自动填充 @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updatedAt; // 创建和更新时自动填充 }
-
实现 MetaObjectHandler 创建一个类实现
MetaObjectHandler
接口,并重写insertFill
和updateFill
方法,定义插入和更新时的填充逻辑。@Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createdAt", LocalDateTime::now, LocalDateTime.class); this.strictInsertFill(metaObject, "updatedAt", LocalDateTime::now, LocalDateTime.class); } @Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "updatedAt", LocalDateTime::now, LocalDateTime.class); } }
-
配置自动填充处理器 确保
MyMetaObjectHandler
类被 Spring 管理,可以通过@Component
或@Bean
注解来实现。 -
使用示例 创建一个继承自
BaseMapper
的 Mapper 接口@Mapper public interface UserMapper extends BaseMapper<User> { }
测试代码
@Component public class MyTestRunner implements CommandLineRunner { @Autowired private UserMapper userMapper; @Override public void run(String... args) throws Exception { // 测试插入时自动填充 User user = new User(); user.setUsername("John Doe"); userMapper.insert(user); System.out.println("Inserted user: " + user); // 测试更新时自动填充 user.setUsername("Jane Doe"); userMapper.updateById(user); System.out.println("Updated user: " + user); } }
两种方式的对比
-
MyBatis 拦截器方式
-
优点:灵活性高,可以自定义复杂的填充逻辑,适用于复杂的业务场景。
-
缺点:实现相对复杂,需要编写较多代码,且需要手动添加注解。
-
-
MyBatis-Plus 方式
-
优点:使用简单,代码量少,开箱即用,与 MyBatis-Plus 无缝集成。
-
缺点:填充逻辑相对固定,扩展性较差。
-
选择建议
-
如果需要实现简单的自动填充功能,如创建时间和更新时间的自动填充,推荐使用 MyBatis-Plus 方式。
-
如果有复杂的业务逻辑,需要自定义填充逻辑,推荐使用 MyBatis 拦截器方式。