在 Java 1.7.0 下运行的 SQL-Server (MSSQL-JDBC 3.0) 中的日期列在过去检索为 2 天

2022-09-03 01:45:43

在官方 Oracle JDK 1.7.0 下运行时,使用 Microsoft JDBC 驱动程序 3.0 从 SQLServer2008 检索 DATE 类型的列时,我有奇怪的效果。Host OS 是 Windows Server 2003。

所有 Date 列都作为过去天相对于列中实际存储的值进行检索。

我编写了一个最小的代码示例来测试它(测试表和数据):

CREATE TABLE Java7DateTest (
  dateColumn DATE
);
INSERT INTO Java7DateTest VALUES('2011-10-10');

法典:

public class Java7SQLDateTest {

    public static void main(final String[] argv) {
        try {
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            Connection connection = DriverManager.getConnection(
                    "jdbc:sqlserver://192.168.0.1:1433;databaseName=dbNameHere",
                    "user", "password");
            PreparedStatement statement = connection.prepareStatement("SELECT * FROM Java7DateTest");
            ResultSet resultSet = statement.executeQuery();
            while (resultSet.next()) {
                final java.sql.Date date = resultSet.getDate("dateColumn");
                final String str = resultSet.getString("dateColumn");
                System.out.println(date + " (raw: " + str + ")");
            }
            resultSet.close();
            statement.close();
            connection.close();
        } catch (final Throwable t) {
            throw new RuntimeException(t.getMessage(), t);
        }
    }

}

在上面的配置上运行此代码打印:“2011-10-08(原始:2011-10-08)”。在 JRE 1.6.0_27 下,它打印:“2011-10-10(原始:2011-10-10)”

我找不到任何似乎与我的谷歌问题有关的东西,所以我假设它要么是我忽略的愚蠢的东西,要么是没有人使用Java7。

任何人都可以确认这个问题吗?如果我仍然想使用Java7,我有什么替代方案?

编辑:即使使用-Xint运行时也会出现问题,因此它不是由热点错误引起的。

编辑2:旧驱动程序(Microsoft 1.28)与JDK1.7.0一起正常工作(我想我们直到两年前才使用该驱动程序)。jTDS也与该示例完美配合。我正在考虑切换到jTDS,但我不愿意这样做,因为我对我们的生产环境可能产生什么影响一无所知。理想情况下,它应该可以工作,但是当我将开发盒切换到Java7时,我也相信这一点。在生产环境中有一个非常胖的数据库,它太大而无法创建副本,用于测试(或者更确切地说,我们的服务器只剩下很少的磁盘)。因此,为该应用设置测试环境并非遥不可及,我必须为此拼接一个缩小的数据库。

Edit3:jTDS附加了自己的一套捕获。我发现了一个行为差异,它破坏了我们的一个应用程序。ResultSet.getObject() 根据驱动程序(短整型与整数)为 SmallInt 列返回不同的对象类型。此外,jTDS 不实现 JDBC4 连接接口,不支持 Connect.isValid()。

Edit4:上周我注意到MSSQL-JDBC 3.0在我更新到JDK1.6.0_29后拒绝连接到任何数据库。jTDS 然后...我们昨天切换了高效的服务器(我修复了应用程序依赖于驱动程序特性的拖曳位置),到目前为止,我们没有任何问题。


答案 1

感谢您的反馈。Microsoft JDBC Driver for SQL Server 尚不支持 JRE 1.7。

我们已知知 JDBC 驱动程序与 JRE 1.7 之间的 getDate 问题,并且我们正在考虑发布修补程序,使客户能够使用 JRE 1.7 对我们的驱动程序进行非生产测试。

一旦可用,我们将在博客上发布指向此修补程序的链接。http://blogs.msdn.com/b/jdbcteam/

此修补程序现已推出。http://blogs.msdn.com/b/jdbcteam/archive/2012/01/20/hotfix-available-for-date-issue-when-using-jre-1-7.aspx

我们的博客还包含有关 JRE 1.6u29 和 1.6u30 的已知问题的信息。

Shamitha Reddy Program Manager - Microsoft JDBC Driver for SQL Server


答案 2

我没有一个答案给你。但是,正如你所描述的那样,我已经重现了你的情况。在 jdk1.7 下运行时,jdbc 驱动程序 v3.101 和 v3.202 以及 v4.ctp3 也是如此。但是,来自 MS 的 v2 驱动程序在 jdk1.6 和 jdk1.7 下都给出了预期的答案。如果您需要快速修复并且可以移动到较旧的jdbc驱动程序,这可能适合您。

其他想法是关于 MS jdbc 驱动程序如何处理日期以及 SQL Server 和 jvm 之间 Date 对象的转换。由于日期的存储没有时区,因此驱动程序对 Date 对象的解释基于运行 jdbc 驱动程序的计算机的默认时区。例如,如果您存储一个小日期 '2011-10-11 12:00' 并从默认时区设置为 GMT-7 的计算机检索它,则 Date 对象的结果 UTC 时间将为 '2011-10-11 19:00'。可能是 jdk1.7 中的某些更改会影响驱动程序中的此转换过程,从而导致异常偏移。您可以尝试使用 ResultSet.getDate(column, Calendar) 方法,看看具有特定时区的日历是否能获得所需的结果,或者有助于理解为什么您在转换中看到奇怪的偏移量。