首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java 日期處理:從資料庫取出時間與當前時間比較的正確姿勢與空指針防護

     編輯:程式設計綜合問答

問題程式碼回顧

SimpleDateFormat lst = new SimpleDateFormat("yyyy-MM-dd");
TransLogInfo transLogInfo = transLogInfoService.QueryTransLogInfo("intTxnDt");
String log = transLogInfo.getIntTxnDt(); // ❌ 可能拋 NPE
Date logTime = lst.parse(log);
GregorianCalendar gc = new GregorianCalendar();
gc.setTime(logTime);

錯誤訊息:Error calling method through OGNL,實際為 transLogInfo 為 null 導致 getIntTxnDt() 拋 NPE。

根本原因

  • QueryTransLogInfo 在查無資料時回傳 null,而非空物件。
  • 直接對 null 呼叫方法導致 NullPointerException,被 OGNL(Struts2/WebWork 表達式語言)包裝為上述錯誤。

修正版:防禦性程式設計

SimpleDateFormat lst = new SimpleDateFormat("yyyy-MM-dd");
TransLogInfo transLogInfo = transLogInfoService.QueryTransLogInfo("intTxnDt");

if (transLogInfo != null && transLogInfo.getIntTxnDt() != null) {
    String log = transLogInfo.getIntTxnDt();
    try {
        Date logTime = lst.parse(log);
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(logTime);
        
        // 取得當前時間比較
        Date now = new Date();
        if (logTime.before(now)) {
            // 邏輯:logTime 早於現在
        } else {
            // 邏輯:logTime 晚於或等於現在
        }
    } catch (ParseException e) {
        log.error("日期格式解析失敗: {}", log, e);
        // 拋出業務異常或預設處理
    }
} else {
    log.warn("查無交易記錄或交易時間為空");
    // 業務預設邏輯
}

現代 Java 時間 API(Java 8+)最佳實務

強烈建議棄用 Date/Calendar/SimpleDateFormat,改用 java.time 套件:

// 假設資料庫欄位為 DATE 或 TIMESTAMP,MyBatis 直接映射為 LocalDate/LocalDateTime
LocalDate txnDate = transLogInfo.getIntTxnDtAsLocalDate(); // 映射方法視實際實作調整

if (txnDate != null) {
    LocalDate today = LocalDate.now(ZoneId.systemDefault()); // 或 ZoneOffset.UTC
    int cmp = txnDate.compareTo(today);
    if (cmp < 0) { /* 過去 */ }
    else if (cmp > 0) { /* 未來 */ }
    else { /* 今天 */ }
}

優勢

  • 不可變、執行緒安全:SimpleDateFormat 非執行緒安全,易在高併發下產生錯誤解析。
  • API 直觀:compareTo、isBefore、plusDays 等語意清晰。
  • 時區處理明確:避免 Date 隱含系統預設時區造成跨環境不一致。

MyBatis 映射建議

<resultMap id="transLogMap" type="TransLogInfo">
    <result column="int_txn_dt" property="intTxnDtAsLocalDate" jdbcType="DATE" javaType="java.time.LocalDate"/>
</resultMap>

或使用 TypeHandler 統一處理 java.time 類型映射。

常見坑點速查

現象原因修正
OGNL NPEService 回傳 null 直接呼叫 getter加 null 檢查或回傳 Optional
ParseException資料庫日期格式與 SimpleDateFormat pattern 不符確認 pattern(yyyy-MM-dd vs yyyy/MM/dd vs timestamp)
時區偏移Date/Calendar 使用 JVM 預設時區改用 java.time 明確指定 ZoneId
執行緒不安全共用 SimpleDateFormat 實例使用 ThreadLocal 或改用 DateTimeFormatter

總結

從資料庫取時間比較,核心要點:1. 防禦性檢查 null、2. 捕捉解析異常、3. 遷移至 java.time 套件。若專案仍在 Java 7,至少將 SimpleDateFormat 改為 ThreadLocal 單例或每次新建,並統一時區設定。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved