前言
上週遇到一個奇怪的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類型,問題解決!
總結
細節不容忽略啊~ 感謝閱讀,表述欠妥之處歡迎多交流~~