分页查询 + Redis缓存 + 缓存中有值时,报错。

Blade 未结 4 1261
anxiaole
anxiaole 2022-01-29 15:20

一、该问题的重现步骤是什么?

  1. 当查询数据库时使用分页查询 并且使用缓存:  

@Cacheable(cacheNames = "my-service-web", key = "#root.method.name + ':' + #root.args[0] + ':' + #root.args[1]")
public IPage selectUserByUserName(String userName, Query query) {
    IPage page = Condition.getPage(query);
    page.setRecords(userMapper.selectByMobile(page, userName));
    return page;
}

2、此时,如果缓存中没有,就会查询数据库,并保存到缓存中。(缓存中没有值时,不会报错。)

3、但是:当第二次调用此方法,此时缓存中有值,就会报错。

4、注意:必须满足三个条件:

 - 使用分页查询     返回值为IPage 

 - 使用缓存 @Cacheable    保存到redis中。(如果缓存是本地jvm内存没有试过)

 - 当redis缓存中有数据时

满足以上三个条件,就一定会报错。



二、你期待的结果是什么?实际看到的又是什么?

       期待:使用分页查询 并且 当命中redis缓存数据时,可以正常从缓存中获取分页数据。


三、你正在使用的是什么产品,什么版本?在什么操作系统上?

       bladex 商业授权版 2.8.1.RELEASE   

       本地和linux服务器上均出现此问题,无论是什么环境,只要缓存中有分页数据,就报错。

       


四、请提供详细的错误堆栈信息,这很重要。

java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at io.protostuff.runtime.RuntimeRepeatedFieldFactory$5.setValue(RuntimeRepeatedFieldFactory.java:311)
	at io.protostuff.runtime.PolymorphicSchemaFactories$11$1.setValue(PolymorphicSchemaFactories.java:247)
	at io.protostuff.runtime.ObjectSchema.mergeFrom(ObjectSchema.java:350)
	at io.protostuff.ByteArrayInput.mergeObjectEncodedAsGroup(ByteArrayInput.java:518)
	at io.protostuff.ByteArrayInput.mergeObject(ByteArrayInput.java:490)
	at io.protostuff.runtime.RuntimeRepeatedFieldFactory$5.mergeFrom(RuntimeRepeatedFieldFactory.java:269)
	at io.protostuff.runtime.RuntimeSchema.mergeFrom(RuntimeSchema.java:466)
	at io.protostuff.runtime.ObjectSchema.readObjectFrom(ObjectSchema.java:693)
	at io.protostuff.runtime.ObjectSchema.mergeFrom(ObjectSchema.java:350)
	at io.protostuff.ByteArrayInput.mergeObjectEncodedAsGroup(ByteArrayInput.java:518)
	at io.protostuff.ByteArrayInput.mergeObject(ByteArrayInput.java:490)
	at io.protostuff.runtime.RuntimeUnsafeFieldFactory$15$1.mergeFrom(RuntimeUnsafeFieldFactory.java:1217)
	at io.protostuff.runtime.RuntimeSchema.mergeFrom(RuntimeSchema.java:466)
	at io.protostuff.IOUtil.mergeFrom(IOUtil.java:45)
	at io.protostuff.ProtostuffIOUtil.mergeFrom(ProtostuffIOUtil.java:104)
	at org.springblade.core.redis.serializer.ProtoStuffSerializer.deserialize(ProtoStuffSerializer.java:59)
	at org.springframework.data.redis.serializer.DefaultRedisElementReader.read(DefaultRedisElementReader.java:48)
	at org.springframework.data.redis.serializer.RedisSerializationContext$SerializationPair.read(RedisSerializationContext.java:272)
	at org.springframework.data.redis.cache.RedisCache.deserializeCacheValue(RedisCache.java:260)
	at org.springframework.data.redis.cache.RedisCache.lookup(RedisCache.java:94)
	at org.springframework.cache.support.AbstractValueAdaptingCache.get(AbstractValueAdaptingCache.java:58)
	at org.springframework.cache.interceptor.AbstractCacheInvoker.doGet(AbstractCacheInvoker.java:73)
	at org.springframework.cache.interceptor.CacheAspectSupport.findInCaches(CacheAspectSupport.java:571)
	at org.springframework.cache.interceptor.CacheAspectSupport.findCachedItem(CacheAspectSupport.java:536)
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:402)
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:346)
	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
	at com.mam.wind.service.WindFundService$$EnhancerBySpringCGLIB$$1b5ff5e7.selectFundAnnouncementPage()
	at com.mam.wind.service.WindFundServiceTest.selectFundAnnouncement(WindFundServiceTest.java:84)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
	at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:221)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)


五、若有更多详细信息,请在下面提供。

      具体原因是:com.baomidou.mybatisplus.extension.plugins.pagination.Page#records 变量,默认值为: Collections.emptyList()  导致的:

/**
 * 查询数据列表
 */
protected List records = Collections.emptyList();


修改方案:

本地重写 com.baomidou.mybatisplus.extension.plugins.pagination.Page   类,并且修改 records 变量为:

/**
 * 查询数据列表
 */
protected List records = new ArrayList();

问题解决了。

(如果此问题不予解决,我就先本地重写这个类了。)

4条回答
  •  usher
    usher (楼主)
    2023-06-08 16:17

    这个大概是因为ipage里面的records是abstractList,你可以去看下他的add,默认就是直接抛异常

提交回复