点击上方名片关注我,为你带来更多踩坑案例
引导
废话不多说,本文从现象-解决办法-原因三个方面来简述
解决办法有多种,大家根据自己的情况自行选择
现象
mysql中的字段是bigint(20)类型,java中实体类的字段是Long类型,写了一个方法大概如下:
@Query(value = "select id from test_people where status = 1", nativeQuery = true)
List<Long> findId();
然后得到一个List<id> ids,取ids中元素的时候报错
java.math.BigInteger cannot be cast to java.lang.Long
想必很多朋友经常碰到这个问题,下面说解决办法
解决办法1-JPQL
这个办法最快捷,直接使用JPQL语句替代原生sql,这样返回的值就是Long啦。
@Query(value = "select id from People where status = 1")
List<Long> findId();
解决办法2-替换jdbc版本
替换jdbc的版本,比如我的版本一开始是
替换为了
我是和springcloud整体做了一个升级,小伙伴们也可以单独升级jdbc及其相关依赖。
<version>2.2.6.RELEASE</version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
关于改到哪个版本,可以具体参考springcloud的兼容性,结合自己项目的实际情况来决定或尝试。
ps:替换之后确保重新下好了依赖并且重新打包
解决办法3-应用层转换
这个方法也比较简单,包括但不限于在应用层中把BigInteger转为String,String再转为Long,以及搞一些自定义类的方法。
我本人是不太推荐这种办法的,有点自欺欺人,但紧急情况下也不失为一种解决办法。
解决办法4-修改接收类
既然BigInteger转不成Long类型,那就不转了呗,数据库bigint字段的值,直接统一用BigInteger接收就好了。
这种方法比较适用于新项目。
原因
究其原因,就是某些版本的jdbc把数据库中的bigint类型映射成了BigInteger类型,而不是预期的Long类型。
可能有朋友会疑惑,bigint是8个字节,Long也是8个字节,有的版本也的确是bigint->Long,为什么要转成BigInteger呢?
那是因为bigint可以是无符号整数,Long是有符号的,当bigint是无符号整数时,二者可表达的最大值就差了一倍了,用Long接的话可能会溢出
所以有些版本直接转成BigInteger了
小附录
可能有些朋友会注意到一个问题,那就是sql的返回值接收参数的时候
List<Long> id1 = projectRepository.findId();
Long aLong = id1.get(0);
也就是第一行并不会报错
但是在第二行取用的时候会报错,这又是为什么?
那是因为java中的泛型仅在编译器生效检查,存在泛型擦除机制,所以导致了牛头接马面的现象,然后直到真正使用的时候才露馅。
大家感兴趣的可以去了解下泛型擦除机制。