一、問題由來
前一天下午正在寫代碼的時候,領導突然走過來跟我說,讓我去看一個神秘的BUG,說是在數據庫中查詢時的一個日期
返回到頁面后,查詢時間倒退了一天。一聽到這個BUG,我就感覺很奇怪,還有這樣的BUG?也讓我滿是期待,究竟是
什么樣的BUG會導致這個問題呢?
二、問題分析
這就是一個很簡單的列表查詢,查詢條件都只有一個怎么出現這么奇怪的BUG呢?我立馬在本地測試了一下,結果還真是時間向前
倒退了一天。這個是查詢的結果,
這個是使用Swagger測試的結果,
以0002這家企業為例,數據庫查詢的tableDate為2020-09-01,可是返回到頁面中時卻是2020-08-31,日期確實向前減了一天。
看到這個測試結果讓我很驚訝,還真神了。這是時間發生錯亂了嘛,還是發生時空穿梭了,問題竟然還真出現了。我去看了另外
一個查詢,只查詢年份的一個接口,結果更神奇,年份的查詢結果為1970年。數據庫查詢結果如下,
頁面中返回的結果為,
自己看到這結果都不得不相信這個現實。接着開始排查原因,查詢年份的數據在返回頁面前打印的數據為,
從打印的結果來看是正確的,沒什么異常。可是查看第一個查詢最后返回的數據時,發現有不對勁的地方,最后返回的是時間戳,而不是字符串的日期。
我將時間戳轉換為日期后發現也是正確的,
接着進一步排查,看看這兩個輸出類中對應的日期字段是什么,
這兩個返回的輸出類中,日期字段都使用了java中的Date類型,並且使用了一個注解JsonFormat注解。這個注解是同事推介使用的,
使用這個注解的好處是,不需要在查詢的SQL中對查詢結果有日期、時間的字段做格式化處理,格式化日期和時間的操作全部放在Java
的輸出類中來進行處理。這樣對於我們開發來說,改動的代碼量會小很多,不然不同的數據庫比如Mysql和Oracle就需要使用不同的語法
進行格式化。對於開發來說,有復雜和簡單的兩種方法來解決問題,如果有得選,那么我一定會選擇簡單的辦法來處理問題。
自己嘗試使用各種辦法,比如格式化日期時使用年月日時分秒,沒有解決;輸出類中使用字符串來接收查詢的日期類型,可以解決。
到此可以確定一點就是格式化這里出問題了。
三、解決方案
和同事說了這個問題后,同事幫忙查詢原因,最終找到一篇文章,找到了這個問題的解決辦法。https://blog.csdn.net/a992795427/article/details/87094200
問題的原因是在使用JsonFormat這個注解時,使用的時區不一樣,默認使用的是標准的格林威治時間,而我們中國所在的時區為東八區,需要在默認
時區上面加8個小時,記得這好像是初中的地理常識。在配置文件中添加上這一行配置之后,
spring.jackson.time-zone=GMT+8
問題解決。另外一個問題,只查詢年份的時候,年份變為1970年的原因是使用JsonFormat注解格式化日期時,不能直接格式化為年份。這是通過實踐
得出的經驗。至此神秘BUG終於解決。