MyBatis与MyBatis-Plus:字段自动填充的两种实现方式

目录

[1. 使用 MyBatis 拦截器实现字段自动填充](#1. 使用 MyBatis 拦截器实现字段自动填充)

[2. 使用 MyBatis-Plus 实现字段自动填充](#2. 使用 MyBatis-Plus 实现字段自动填充)


1. 使用 MyBatis 拦截器实现字段自动填充

实现步骤
  1. 创建拦截器 实现 MyBatis 的 Interceptor 接口,通过拦截 MyBatis 执行的 SQL 操作来自动填充公共字段

    java 复制代码
    @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) {
            // 可选:设置属性
        }
    }
  2. 定义基础实体类 创建一个基础实体类 BaseEntity,包含需要自动填充的公共字段,所有需要自动填充的实体类都应继承该类

    java 复制代码
    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;
        }
    }
  3. 配置拦截器 在 MyBatis 配置文件中注册拦截器

    XML 复制代码
    <plugins>
        <plugin interceptor="com.example.mybatis.interceptor.CommonFieldInterceptor"/>
    </plugins>
  4. 使用示例 创建一个继承 BaseEntity 的实体类,并在 Mapper 中使用该实体类进行数据库操作

    java 复制代码
    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;
        }
    }
    java 复制代码
    @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 实现字段自动填充

实现步骤
  1. 定义实体类 在实体类中,使用 @TableField 注解来标记需要自动填充的字段,并指定填充策略

    java 复制代码
    @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;  // 创建和更新时自动填充
    }
  2. 实现 MetaObjectHandler 创建一个类实现 MetaObjectHandler 接口,并重写 insertFillupdateFill 方法,定义插入和更新时的填充逻辑。

    java 复制代码
    @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);
        }
    }
  3. 配置自动填充处理器 确保 MyMetaObjectHandler 类被 Spring 管理,可以通过 @Component@Bean 注解来实现。

  4. 使用示例 创建一个继承自 BaseMapper 的 Mapper 接口

    java 复制代码
    @Mapper
    public interface UserMapper extends BaseMapper<User> {
    }

    测试代码

    java 复制代码
    @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 拦截器方式

相关推荐
灵魂猎手7 分钟前
11. Mybatis SQL解析源码分析
java·后端·源码
努力的小郑35 分钟前
别再说你会 new Object() 了!JVM 类加载的真相,绝对和你想的不一样
java·jvm·面试
cxyxiaokui00139 分钟前
论如何优雅地让AI“闭嘴”:深入SpringAI的流式停止与记忆难题
java·后端
嗝屁小孩纸42 分钟前
使用EasyExcel自定义导出表格
java·excel
the beard1 小时前
深入理解Java多线程:状态、安全、同步与通信
java·开发语言
pengzhuofan1 小时前
Java设计模式-享元模式
java·设计模式·享元模式
灵魂猎手2 小时前
10. Mybatis XML配置到SQL的转换之旅
java·后端·源码
掉鱼的猫2 小时前
10分钟带你体验 Solon 的状态机
java
皮皮林5512 小时前
从一个程序员的角度告诉你:“12306”有多牛逼?
java
AAA修煤气灶刘哥2 小时前
被参数校验 / 日志逼疯?AOP:1 个切入点,所有方法自动加 buff
java·后端·面试