最近开发过程中,居然碰到了一个Arrays.asList的错,怎么个场景呢?传参一个用固定符号拼接的字符串,需要转成集合然后再myBatis里in判断。然后就报错了。
一、代码层面
service层面:
java
shortDetailUrlList = Arrays.asList(params.getShortDetailUrl().split("-"));
mybatis层面:
xml
<if test="shortDetailUrlList != null and shortDetailUrlList.size() > 0">
and tcp.short_url in
<foreach item="shortDetailUrl" collection="shortDetailUrlList" open="(" separator="," close=")"
index="index">
#{shortDetailUrl}
</foreach>
</if>
二、错误日志
bash
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.reflect.InaccessibleObjectException: Unable to make public int java.util.Arrays$ArrayList.size() accessible: module java.base does not "opens java.util" to unnamed module @65e579dc
### Cause: java.lang.reflect.InaccessibleObjectException: Unable to make public int java.util.Arrays$ArrayList.size() accessible: module java.base does not "opens java.util" to unnamed module @65e579dc
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:96)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:441)
at jdk.proxy2/jdk.proxy2.$Proxy103.selectList(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224)
at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:147)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:80)
at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:145)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
at jdk.proxy2/jdk.proxy2.$Proxy152.getConstructInfoByReceiveId(Unknown Source)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:577)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
at jdk.proxy2/jdk.proxy2.$Proxy153.getConstructInfoByReceiveId(Unknown Source)
at com.meta.image.admin.service.impl.ReportBaseServiceImpl.getReportConstructInfo(ReportBaseServiceImpl.java:389)
at com.meta.image.admin.controller.ReportBaseV2Controller.getReportConstructInfo(ReportBaseV2Controller.java:75)
at com.meta.image.admin.controller.ReportBaseV2Controller$$FastClassBySpringCGLIB$$b659f1a1.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
三、日志分析
根据错误日志可以晓得:数据库报错了,然后还是反射的错。错误的根源就是:
bash
Unable to make public int java.util.Arrays$ArrayList.size() accessible
那这错误的根源到底是什么呢?那还得从Array.asList分析入手啊。。。
四、Array.asList的坑
1、使用场景
一般我们字符串切割,很容易想到额就是它了,固定符号分割,获取一个集合列表。
【注意】:
- 该方法适用于对象型数据的数组(String、Integer...)
- 该方法不建议使用于基本数据类型的数组(byte,short,int,long,float,double,boolean)
- 该方法将数组与List列表链接起来:当更新其一个时,另一个自动更新
- 不支持add()、remove()、clear()等方法
2、为何说是一个坑?
① :此方法得到的List的长度是不可改变的(看源码就会一目了然)
当你向这个List添加或删除一个元素时(例如 list.add("d");)程序就会抛出异尝(java.lang.UnsupportedOperationException)。
java
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
/**
* @serial include
*/
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
看源码你就会发现,每次调用asList,都是new一个新的,来操作增删。
②:虽然也是集合,但是确实内部类,和我们所用的java.util.arrayList是不一样的
回到第三点,为何会报反射异常,因为内部类,mybatis去获取size的时候,是获取不到的。解决办法也有很多种。