Mybatis-plus构建wrapper条件时出现索引越界异常Caused by: org.apache.ibatis.exceptions.PersistenceException: ### E

本文讲述了在使用SpringBoot和MyBatis-Plus进行项目开发时,遇到控制台索引越界异常的问题,经过分析发现是由于全字段构造器与查询结果列数不符导致。解决方案包括移除全字段构造器注解或添加无参构造方法。
摘要由CSDN通过智能技术生成

项目场景:

学习springboot整合mybatis-plus时通过构建器执行相关操作

@Autowired
BookMapper mapper;

@Test
void test(){
    QueryWrapper<Book> wrapper = new QueryWrapper<>();
    wrapper
            .select("id", "name", "press") //只查询前三个字段
            .gt("id", 1 ) //只要id>1的列
            .like("name","%计算机%"); //名字中有计算机的
    System.out.println(mapper.selectList(wrapper));
}

问题描述

控制台出现索引越界异常

### Error querying database.  Cause: java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
### The error may exist in com/lmw/mapper/BookMapper.java (best guess)
### The error may involve com.lmw.mapper.BookMapper.selectList
### The error occurred while handling results
### SQL: SELECT   id,name,press   FROM tb_book      WHERE  (id > ? AND name LIKE ?)
### Cause: java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:156)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:142)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:425)
    ... 11 more

此时将构建器中的select条件去掉,竟然执行成功了


原因分析:

查看控制台的SQL日志

Preparing: SELECT id,name,press,author FROM tb_book WHERE (id > ? AND name LIKE ?)

如果去掉 select() 就是查询全部列(成功),不去掉就是查询指定列(报错)

分析代码执行流程:传入构建器wrapper--构建SQL语句--生成对应筛选where条件--返回select指定列数据--封装成实体类对象--输出

因此可以判断问题出在 select返回指定列数据--封装成实体类对象 这一步

然而这一步骤是通过调用实体类的构造方法完成的,此时我们进入实体类查看:

可以注意到类名上面打上了 @AllArgsConstructor 注解,该注解的作用相当于为这个类指定了一个全字段构造方法,到这里报错的原因大概就能知道了

由于我们指定了一个全字段的构造方法,且并没有其他无参或有参的构造方法,那么在mybatis-plus替我们封装数据的时候就会出问题:我们只拿到了其中的几列数据,但构造器要求我们提供所有的字段数据,自然就报错了。至于为什么是索引越界异常,我的猜想:

mapper执行完查询后返回的是一个有序的数据集合,每一个列占一个索引,在封装成对象的时候,调用一个仅有全字段构造方法,此时构造方法会从返回的数据集合中读取相应的字段,读取到一半时,集合中的数据已经读完了,但构造方法还没结束,所以继续往下读,此时便发生了索引越界异常。

纯个人猜想,欢迎指正~


解决方案:

1.去掉@AllArgsConstructor注解,此时会有一个默认的无参构造方法

    

@Data
@TableName("tb_book")
//@AllArgsConstructor
public class Book {
        ...
}

2.手动加上一个无参构造方法

@Data
@TableName("tb_book")
@AllArgsConstructor
public class Book {

   public Book(){
        
   }
        
   ...

}

测试运行,可以看到两种方法都执行成功了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值