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

Dur*_*dal 16 java sql-server date jdbc

在官方Oracle JDK 1.7.0下运行时,使用Microsoft JDBC-Driver 3.0版从SQLServer2008检索DATE类型的列时,我会产生奇怪的效果.主机操作系统是Windows Server 2003.

所有日期栏,为检索两个天过去相对于实际存储在列中的值.

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

CREATE TABLE Java7DateTest (
  dateColumn DATE
);
INSERT INTO Java7DateTest VALUES('2011-10-10');
Run Code Online (Sandbox Code Playgroud)

码:

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);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

在上面的配置上运行此代码打印:"2011-10-08(raw:2011-10-08)".在JRE 1.6.0_27下打印:"2011-10-10(raw:2011-10-10)"

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

谁能证实这个问题?如果我还想使用Java7,我还有什么选择?

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

Edit2:旧驱动程序(Microsoft 1.28)与JDK1.7.0一起正常工作(我想在两年前使用该驱动程序,我认为).jTDS也可以与这个例子完美搭配.我正在考虑转用jTDS,但我不愿意这样做,因为我不知道对我们的生产环境的影响可能是什么.理想情况下它应该可以工作,但是当我将开发框切换到Java7时我也相信了.在生产环境中有一个非常胖的数据库,它太大了,无法创建一个副本,用于测试(或者说我们的服务器剩下这么少的磁盘).因此,为那个应用程序设置一个测试环境并不是一个简单的方法,我必须为此设置一个缩小的数据库.

Edit3:jTDS附有自己的一系列捕获.我发现了一个违反我们应用程序的行为差异.ResultSet.getObject()根据驱动程序(Short vs Integer)返回SmallInt列的不同对象类型.此外,jTDS未实现JDBC4 Connection接口,不支持Connect.isValid().

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

小智 10

感谢您的反馈意见.用于SQL Server的Microsoft JDBC驱动程序尚不支持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项目经理 - 用于SQL Server的Microsoft JDBC驱动程序


phi*_*lwb 8

我找不到你的答案.但是,正如你所描述的那样,我重新创造了你的情况.在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"的smalldate并从默认时区设置为GMT-7的计算机中检索它,则Date对象的生成UTC时间将为"2011-10" -11 19:00'.可能是jdk1.7中存在一些变化会影响驱动程序中的转换过程,从而导致偏移.您可以尝试使用ResultSet.getDate(列,日历)方法来查看具有特定时区的日历是否可以获得您想要的结果,或者有助于了解您在转换中看到奇怪偏移的原因.