当前位置: 首页 > 面试题库 >

错过了在Java 8中修复JDBC日期处理的机会吗?

百里沛
2023-03-14
问题内容

在以下推理中,任何Java 8 + JDBC专家都可以告诉我是否有问题吗?而且,如果在众神的秘密中,为什么还没有这样做呢?

java.sql.Date是目前使用的JDBC映射到SQL
DATE类型,这表示日期无时间,没有时区的类型。但是,该类经过了精心设计,因为它实际上是的子类java.util.Date,可存储精确的时间(最多毫秒)。

为了在数据库中表示日期2015-09-13,我们被迫选择一个时区,将该时区中的字符串“
2015-09-13T00:00:00.000”解析为java.util.Date以获取毫秒数。值,然后java.sql.Date从该毫秒值构造一个a
,最后调用setDate()准备好的语句,传递一个Calendar,该日历保存选择的时区,以便JDBC驱动程序能够从该毫秒值正确地重新计算日期2015-09-13。通过在各处使用默认时区,而不传递日历,可以使此过程变得更简单。

Java 8引入了LocalDate类,该类更适合DATE数据库类型,因为它不是精确的时间点,因此不依赖于时区。Java
8还引入了默认方法,该方法允许对PreparedStatement和ResultSet接口进行向后兼容的更改。

因此,难道我们没有错过一个巨大的机会来清理JDBC中的混乱情况,同时仍保持向后兼容性吗?Java
8可以简单地将这些默认方法添加到PreparedStatement和ResultSet中:

default public void setLocalDate(int parameterIndex, LocalDate localDate) {
    if (localDate == null) {
        setDate(parameterIndex, null);
    }
    else {
        ZoneId utc = ZoneId.of("UTC");
        java.util.Date utilDate = java.util.Date.from(localDate.atStartOfDay(utc).toInstant());
        Date sqlDate = new Date(utilDate.getTime());
        setDate(parameterIndex, sqlDate, Calendar.getInstance(TimeZone.getTimeZone(utc)));
    }
}

default LocalDate getLocalDate(int parameterIndex) {
    ZoneId utc = ZoneId.of("UTC");
    Date sqlDate = getDate(parameterIndex, Calendar.getInstance(TimeZone.getTimeZone(utc)));
    if (sqlDate == null) {
        return null;
    }

    java.util.Date utilDate = new java.util.Date(sqlDate.getTime());
    return utilDate.toInstant().atZone(utc).toLocalDate();
}

当然,相同的推理适用于对TIMESTAMP类型的Instant支持,以及对TIME类型的LocalTime支持。


问题答案:

为了在数据库中表示日期2015-09-13,我们被迫选择一个时区,将该时区中的字符串“
2015-09-13T00:00:00.000”解析为java.util.Date以获取毫秒数。值,然后从该毫秒值构造一个java.sql.Date,最后在准备好的语句上调用setDate(),传递一个Calendar,该Calendar保存所选时区,以便JDBC驱动程序能够正确地重新计算日期2015-09从该毫秒值开始为-13

为什么?刚打电话

Date.valueOf("2015-09-13"); // From String
Date.valueOf(localDate);    // From java.time.LocalDate

该行为将是所有JDBC驱动程序中的正确行为:没有时区的本地日期。逆运算为:

date.toString();    // To String
date.toLocalDate(); // To java.time.LocalDate

您永远不应依赖java.sql.Date的依赖java.util.Date,并且事实也因此依赖于它继承了java.time.Instantvia
Date(long)Date.getTime()

因此,难道我们没有错过一个巨大的机会来清理JDBC中的混乱情况,同时仍保持向后兼容性吗?[…]

这取决于。在JDBC
4.2规范指定,你是能够结合LocalDate通过类型setObject(int, localDate),并获取一条LocalDate通过型getObject(int, LocalDate.class)驱动程序是否做好准备。default当然,不像您建议的那样正式的方法那么优雅。



 类似资料:
  • 问题内容: 我收到此异常: 源自此代码: 哪里是。 所以这对我来说很好- 我知道数据库中存在零日期,我需要能够读取这些日期并将其转换为下游数据结构中的适当数据(可能为空)。问题是我不知道如何检索它并得到“软”错误。我考虑过将这一行包装在SQLException的try / catch中,但了解这会破坏ResultSet的有效性。 是否有可能以其他方式读取此值而不会引发SQLException? 问

  • 我得到了这个例外: 源自此代码: 其中是一个。 所以这对我来说很好-我知道数据库中有零日期,我需要能够读取这些数据并将它们转换为下游数据结构中适当的(可能为空)数据。问题是我不知道如何检索它并得到一个“软”错误。我曾考虑将这一行包装成try/catch for SQLException,但我知道这会破坏ResultSet的有效性。 是否可以以另一种方式读取此值而不引发SQLException?

  • 问题内容: 在使用SQL时,我是一个新手,我想做的是仅使用月份和年份选择waterUsage和lectriccityUsage,然后从上一年中选择waterUsage和lectriccityUsage。 但是,我似乎无法找出使用日期的适当方法来完成这项工作。 表:每月帐单 或者 问题答案: 一种选择是使用: 假设您实际上使用的是Oracle,而不是SQL Server。 如果需要,然后继续,然后在

  • 问题内容: 在Laravel 5中处理过期令牌的最佳方法是什么 我的意思是我有一个页面,并且有一些执行ajax请求的链接。当页面加载时,它们工作正常,但是当我等待一段时间后,出现TOKEN MISMATCH错误。 现在,我必须刷新页面以使其重新工作。但是,我不想刷新页面。我想要某种方式来刷新令牌或其他解决方法以使其更正。 我希望你明白我的意思。 问题答案: 解决方法是实际上每隔一定时间获取新令牌,

  • 主要内容:1 局部处理日期,2 全局处理日期Fastjson默认情况下对日期格式是没有做格式化处理的,默认输出日期的毫秒数。如下: 运行结果为: 如果希望对日期进行格式化输出,可以使用以下方式进行。 1 局部处理日期 局部处理日期,是指可以把toJSONString() 方法换成toJSONStringWithDateFormat() 方法 1.1 编写测试类 MainApp: 1.2 运行结果 2 全局处理日期 全局处理日期,是指统一对需

  • 使用 Servlet 的最重要的优势之一是,可以使用核心 Java 中的大多数可用的方法。本章将讲解 Java 提供的 java.util 包中的 Date 类,这个类封装了当前的日期和时间。 Date 类支持两个构造函数。第一个构造函数初始化当前日期和时间的对象。 Date( ) 下面的构造函数接受一个参数,该参数等于 1970 年 1 月 1 日午夜以来经过的毫秒数。 Date(long