报错:
Cannot construct instance of `java.time.LocalDateTime` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('2019-10-21 13:57:38')
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: java.util.ArrayList[0]->com.construn.vehicle.tmrp.entity.IncomeSummaryRepInfo["createTime"])
java.lang.IllegalArgumentException: Cannot construct instance of `java.time.LocalDateTime` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('2019-10-21 13:57:38')
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: java.util.ArrayList[0]->com.construn.vehicle.tmrp.entity.IncomeSummaryRepInfo["createTime"])
在线上发现的这个问题,大概意思是对LocalDataTime反序列化错误。在本地也有这个问题,我本地和线上的配置、分支都是一样的,所以先排除是环境问题。
刚开始比较奇怪的是用postman对其请求,第一次成功,后面几次就都报错了。查找问题的时候上网查过,大家都说是对redis操作的时候LocalDataTime类型反序列化处理错误,但是我好像没有看到有对redis数据库进行操作,后来发现是@Cacheable这个注解搞的鬼
后来终于发现了错误,报错原因是mappe中的接口加了@Cacheable(cacheNames = FillCacheConstants.CORE_EMP_CACHE_NAME, unless = "#result == null ")这个注解,这个注解会在每次对数据库进行操作的时候,参数一样的前提下,先去redis查看有没有这个数据的缓存,如果有的话就从缓存里拿,没有的话就才会对数据库进行操作。
第一次请求的时候,程序进入redis发现没有这部分数据,就会向数据库请求,这时候对localdatatime的转化没有问题。问题出在后续的请求,后续请求程序进入redis缓存,发现有这个数据,就会把数据从redis反序列化出来,但是这时候因为实体类里面有localdatatime这个类型,而redis对jdk8的这个类型处理有问题,所以会报错
解决方法:
1.如果实体类中没有用到LocalDateTime类型的这个数据,可以换一个实体类,把.LocalDateTime去掉
2.如果要用到LocalDateTime这个类型的数据,可以在其上面添加 @JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)的注解,也可以解决问题
3.在项目的redis配置类里面, redisCacheTemplate在会有一个配置,template.setValueSerializer(new GenericJackson2JsonRedisSerializer());,GenericJackson2JsonRedisSerializer是spring提供的一个默认类,把GenericJackson2JsonRedisSerializer换成其他的类也可以(具体需要你去去另外百度一下,我不打算用这个方法所以没去查),但是可能会牵扯到项目的其他用到redis的地方,所以需要用前需要思考一下。