使用MyBatis批量插入数据,MyBatis拦截器失效?

使用MyBatis批量插入数据,MyBatis拦截器失效?
问题描述:我在项目中写了一个MyBatis的拦截器(插件),作用是在插入或更新数据时自动填充id、create_by、create_time等基础字段的值,代码如下:

@Component
@Intercepts({
        @Signature(type = Executor.class,method = "update",args = {MappedStatement.class, Object.class})
})
public class MyBatisAutoFillPlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 被代理的对象
        Object target = invocation.getTarget();
        // 被代理的方法
        Method method = invocation.getMethod();
        // 被代理的方法执行参数
        Object[] args = invocation.getArgs();

        if (!(args.length > 1)){
            return invocation.proceed();
        }

        MappedStatement mappedStatement = (MappedStatement) args[0];
        Object paramObj = args[1];
        if (paramObj instanceof BaseEntity){
            // 获取登录用户
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            SysLoginUser sysLoginUser = (SysLoginUser) authentication.getPrincipal();

            BaseEntity entity = (BaseEntity) paramObj;
            Date now = new Date();
            // 判断sql语句
            if (Objects.equals(SqlCommandType.INSERT,sqlCommandType)){
                entity.setId(IdGenerator.getId());
                entity.setStatus(CommonStatusEnum.NORMAL.getCode());
                entity.setCreateBy(sysLoginUser.getId());
                entity.setCreateTime(now);
            }else if (Objects.equals(SqlCommandType.UPDATE,sqlCommandType)){
                entity.setUpdateBy(sysLoginUser.getId());
                entity.setUpdateTime(now);
            }
        }
        // 调用实际业务方法
        Object result = invocation.proceed();
        return result;
    }
}

当我在Mapper中写了一个批量插入的方法,执行后拦截器却失效了,导致我的基础字段无法赋值,这是什么原因?

<!-- 批量插入 -->
<insert id="insertBatch">
        insert into sys_user_role
        ( id,user_id,role_id
        ,status,create_time,create_by
        ,update_time,update_by) values
        <foreach collection="list" separator="," item="item">
            (#{item.id},#{item.userId},
             #{item.roleId},
             #{item.status}, #{item.createTime},#{item.createBy},
             #{item.updateTime},#{item.updateBy})
        </foreach>
    </insert>

我尝试使用单个插入的方法,这是可以的。

<!-- 单个记录插入 -->
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.ss.sys.modular.role.entity.UserRole" useGeneratedKeys="true">
        insert into sys_user_role
        ( id,user_id,role_id
        ,status,create_time,create_by
        ,update_time,update_by)
        values (#{id,jdbcType=BIGINT},#{userId,jdbcType=BIGINT},#{roleId,jdbcType=BIGINT}
        ,#{status,jdbcType=TINYINT},#{createTime,jdbcType=TIMESTAMP},#{createBy,jdbcType=BIGINT}
        ,#{updateTime,jdbcType=TIMESTAMP},#{updateBy,jdbcType=BIGINT})
    </insert>
阅读 1.9k
avatarAI BotBETA

你的问题在于批量插入数据时,每个对象的属性值并没有被单独处理,而是以集合的方式一次性插入数据库。这就导致你的拦截器在处理单个对象时,无法正确地处理集合中的每一个对象。

当你使用单个插入的方法时,每个对象的属性值都会被单独处理,所以拦截器可以正常工作。但在批量插入时,所有的对象都是一起处理的,所以拦截器无法正确地为每个对象的属性赋值。

为了解决这个问题,你可以尝试修改你的拦截器,让它能够处理批量插入的情况。具体来说,你需要修改拦截器的intercept方法,让它能够处理集合中的每一个对象,并为每个对象的属性赋值。

另外,你还需要注意,批量插入数据时,可能存在某些对象没有某些属性值的情况。你需要确保在处理集合中的每个对象时,能够正确地处理这种情况。

希望这个答案能够帮助你解决问题。如果你还有其他问题,欢迎继续提问。

2 个回答
✓ 已被采纳

找到原因了,在@Intercepts注解添加要拦截的StatementHandler方法即可

@Intercepts({
        @Signature(type = Executor.class,method = "update",args = {MappedStatement.class, Object.class}),
        @Signature(type = StatementHandler.class,method = "update",args = {Statement.class})
})
public class MyBatisAutoFillPlugin implements Interceptor {
    // some code...
}
if (paramObj instanceof BaseEntity)

这里问题吧,入参是个集合

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题