You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java连接MariaDB按日期查询的正确方法及异常解决

Java与MariaDB环境下按日期查询datetime字段的正确方法

问题背景

以下是用于按日期范围查询document_manager表的Java代码:

public List<DocumentManagerDTO> getDocumentManager(java.sql.Date fromDateInclusive, java.sql.Date toDateInclusive) {
        String query = "select * from document_manager where dataReferencia >= ? and dataReferencia <= ?";
        
        QueryRunner run = new QueryRunner();
        
        ResultSetHandler<List<DocumentManagerDTO>> h = new BeanListHandler<DocumentManagerDTO>(DocumentManagerDTO.class);

        List<DocumentManagerDTO> docsToRet = null;
        try {
            docsToRet = run.query(conn, query, h, fromDateInclusive, toDateInclusive);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        
        return docsToRet;
    }

预期生成的SQL语句为:

select * from document_manager where dataReferencia >= '2023-12-04' and dataReferencia <= '2023-12-18'

该SQL在MySQL Workbench中可正常返回结果,但Java代码运行时抛出以下异常:

java.sql.SQLException: Out of range value for column 'dataReferencia' : value 2023-12-08 00:00:00 Query: select * from document_manager where dataReferencia >= ? and dataReferencia <= ? Parameters: [2023-12-06, 2023-12-20]
    at org.apache.commons.dbutils.AbstractQueryRunner.rethrow(AbstractQueryRunner.java:363)
    at org.apache.commons.dbutils.QueryRunner.query(QueryRunner.java:350)
    at org.apache.commons.dbutils.QueryRunner.query(QueryRunner.java:211)
    at infoasset.mining.connection.DBInterface.getDocumentManager(DBInterface.java:188)
    at infoasset.mining.fnet.ProcessXML.processXMLs(ProcessXML.java:100)
    at infoasset.mining.entry.EntryPointMining.main(EntryPointMining.java:24)

数据库表document_manager的结构如下:

CREATE TABLE `document_manager` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `descriptionDocument` varchar(500) DEFAULT NULL,
  `dataReferencia` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2739 DEFAULT CHARSET=latin1

问题原因

数据库中dataReferencia字段为datetime类型(包含日期和时间),而Java代码使用java.sql.Date作为参数(仅包含日期部分)。JDBC驱动在绑定参数时会自动为java.sql.Date补全时间为00:00:00,但MariaDB对参数类型与字段类型的匹配要求严格,旧版本驱动或默认配置下容易出现类型映射异常,导致抛出“值超出范围”的错误。

正确解决方法

方法1:改用java.sql.Timestamp作为参数类型

java.sql.Timestamp对应数据库的datetime类型,包含完整的日期和时间信息,能完美匹配字段类型。修改后的代码如下:

public List<DocumentManagerDTO> getDocumentManager(java.sql.Timestamp fromDateInclusive, java.sql.Timestamp toDateInclusive) {
    String query = "select * from document_manager where dataReferencia >= ? and dataReferencia <= ?";
    
    QueryRunner run = new QueryRunner();
    ResultSetHandler<List<DocumentManagerDTO>> h = new BeanListHandler<>(DocumentManagerDTO.class);

    List<DocumentManagerDTO> docsToRet = null;
    try {
        docsToRet = run.query(conn, query, h, fromDateInclusive, toDateInclusive);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    
    return docsToRet;
}

如果仅需基于日期查询,可将LocalDate转换为Timestamp:

// 示例:将LocalDate转为当天0点的Timestamp
LocalDate fromLocal = LocalDate.of(2023, 12, 6);
Timestamp fromTs = Timestamp.valueOf(fromLocal.atStartOfDay());

方法2:在SQL中显式转换参数类型

若不想修改Java方法的参数类型,可在SQL语句中显式将java.sql.Date参数转换为datetime类型,或调整查询范围以覆盖当天所有时间:

-- 方法2.1:显式转换参数类型
select * from document_manager 
where dataReferencia >= CAST(? AS DATETIME) 
and dataReferencia <= CAST(? AS DATETIME)
-- 方法2.2:调整结束时间为当天23:59:59,确保覆盖所有datetime记录
select * from document_manager 
where dataReferencia >= ? 
and dataReferencia <= DATE_ADD(?, INTERVAL 1 DAY - 1 SECOND)

方法3:优化JDBC驱动配置

  • 确保使用最新版本的MariaDB JDBC驱动,避免旧版本的类型映射bug。
  • 在数据库连接URL中添加以下参数,启用标准日期时间处理逻辑:
jdbc:mariadb://localhost:3306/your_database?useLegacyDatetimeCode=false&serverTimezone=UTC

useLegacyDatetimeCode=false会禁用旧的日期时间处理逻辑,采用JDBC 4.2标准的类型映射规则,减少类型不匹配的问题。

内容的提问来源于stack exchange,提问作者orochi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:36:03