【报错记录】MybatisPlus报Mapped Statements collection does not contain value for...

前言

为了让我的SqlUtil用起来更香,我准备将SqlHelper中的saveOrUpdateBatch方法的参数从Class<?> mapper换成mapper的实体类,再通过mapper.getClass()的方式获取其真实类。

报错信息

如果是批量插入会报:

Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.sun.proxy.$Proxy129.insert

如果是执行批量更新则会报:

Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.sun.proxy.$Proxy129.updateById

代码如下:

    public static <T extends BaseEntity, R extends BaseMapper<T>> void saveBatch(Class<R> mapperClass, List<T> entityList, Long userId) {
        saveBatch(mapperClass, entityList, userId, 10000);
    }

    public static <T extends BaseEntity, R extends BaseMapper<T>> void saveBatch(R mapper, List<T> entityList, Long userId) {
        saveBatch(mapper.getClass(), entityList, userId, 10000);
    }
    
    public static <T extends BaseEntity, R extends BaseMapper<T>> void saveBatch(Class<R> mapperClass, List<T> entityList, Long userId, int batchSize) {
        if (entityList.size() == 0) {
            return;
        }
        T t = entityList.get(0);
        Class<T> entityClass = (Class<T>) t.getClass();
        SqlHelper.saveOrUpdateBatch(entityClass, mapperClass, log, entityList, batchSize, (sqlSession, entity) -> {
            // INFO: DCTANT: 2021/12/27 insert判断,返回true则是走insert代码,返回false则会走后面的update代码
            if (entity == null) {
                return false;
            }
            Long id = entity.getId();
            if (id == null) {
                // INFO: DCTANT: 2021/12/27 insert前加一些自己必要的业务逻辑,如setCreateTime、setDel、setVersion等等
                insertNecessaryField(entity, userId);
                return true;
            } else {
                // INFO: DCTANT: 2021/12/27 去执行update的代码
                return false;
            }
        }, (sqlSession, entity) -> {
            // INFO: DCTANT: 2021/12/27 判断为update,然后执行必要操作 
            if (entity == null) {
                return;
            }
            // INFO: DCTANT: 2021/12/27 update前加一些自己的业务逻辑,如setUpdateTime等等
            updateNecessaryField(entity, userId);
            MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
            // INFO: DCTANT: 2022/8/22 参数需要为Constants.ENTITY,也就是里面的et,否则会报et这个参数无法找到
            param.put(Constants.ENTITY, entity);
            String sqlStatement = SqlHelper.getSqlStatement(mapperClass, SqlMethod.UPDATE_BY_ID);
            sqlSession.update(sqlStatement, param);
        });
    }

这个问题一开始报的让人摸不着头脑,若不是开了上帝视角,从前言中已经知道大概的问题原由,真是让人一头雾水,proxy类是哪来的,insert和updateById方法这两个方法在mapper中本来就有,凭什么会找不到!

这里一共三种写法,其中2、3是等价的

 第一种写法打断点可得知拿到的就是Mapper它自己本身的类

这种写法能够反射获取其中的insert和updateById方法。

而第二、三种方法打断点获得的类是

实际是Java的代理类,Proxy类,这里面哪会存在insert和updateById方法,这就是报错的原因。所以方法不能胡乱抽取,这种就属于得不偿失,且无解。只能将本身的Class传入才能不报错,删除刚才的saveBatch(Class<R> mapperClass, List<T> entityList, Long userId)这个方法即可。 

如果大家有什么其他解法可以指出,本人虚心接受。

猜你喜欢

转载自blog.csdn.net/DCTANT/article/details/126468022
今日推荐