前言
上周遇到一个奇怪的bug,写了一个查询方法,将sql 拿到数据库中执行是可以查到数据的,但是前台调用接口时就报错500 ,下面来说下我遇到的坑。
正文
问题再现 |
1、前端调用接口(vue.js)
initPaper() {
//初始化参数,默认数值类型
var id = 1158316836366979072;
var year = "0";
this.operPaper = { id: id, year: year };
this.getPaperById();
}
// 异步调用后台接口(getPaperById)
async getPaperById() {
const resp = await getPaperById(this.operPaper);
if (resp != null && resp.status === "0") {
……
}
}
// 页面加载时调用查询方法
created() {
this.initPaper();
}
2、后端接口运行时报错
javax.persistence.NoResultException: No entity found for query
at org.hibernate.query.internal.AbstractProducedQuery.getSingleResult
解决问题 |
一开始还以为是entityManager.createNativeQuery() 这一 Hibernate 的原生查询有问题,因为程序中有neo4j 和 mysql 两种数据源,而且都用到了原生查询语句,还以为是两种冲突了(当然这么用也不优雅),然后就是百度尝试重写EntityManagerFactory中创建EntityManager,然而并没有什么用,纳尼,我要怀疑人生了!!!
后来,想到getSingleResult()这个方法第一次用,为什么会报这种错呢?让我来跟进去看一看,这个接口是咋实现的:
@Override
public R getSingleResult() {
try {
final List<R> list = list();
// 这种情况下(没有查询到记录)会报这厮错误
if ( list.size() == 0 ) {
throw new NoResultException( "No entity found for query" );
}
return uniqueElement( list );
}
catch ( HibernateException e ) {
if ( getProducer().getFactory().getSessionFactoryOptions().isJpaBootstrap() ) {
throw getExceptionConverter().convert( e );
}
else {
throw e;
}
}
}
也就是说没有查询到结果,那就来看看为啥没有结果咧???
数据库里是有数据的:
那就看看代码,估计又写bug了,看日志传参最后三位给整成0了,难怪查不到!
前端传过来的时候就是有误的数据:
分析原因 |
web前端的数据类型:数值类型(number/Number)、字符串类型(string/String)、布尔类型(boolean/Boolean)、空(null)、未定义(undefined)、对象类型(Object)、数组类型(Array)、日期类型(Date)、
函数(Function、Math)、正则表达式(RegExp)等。
Js(JavaScript) 遵循IEEE754规范,采用双精度存储,占用64位,从左到右的安排位第一问表示符号位,11位表示指数,52位来表示尾数,因此Js中能精确表示的最大整数是2^53 (十进制 为 9007199254740992)大于这个数(本文中数值长度19位)就可能会丢失精度,因为二进制只有0和1,数值太大,于是就出现了精度丢失的问题,
解决办法 |
将数值类型的id改为字符串类型,传到后台字符串转成Long类型,问题解决!
总结
细节不容忽略啊~ 感谢阅读,表述欠妥之处欢迎多交流~~