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

在官方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'); 

码:

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

我找不到你的答案。 但是,正如你所描述的那样,我重新创造了你的情况。 在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(column,Calendar)方法来查看具有特定时区的日历是否可以获得您想要的结果,或者有助于了解您在转换中看到奇怪偏移的原因。

感谢您的反馈意见。 用于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驱动程序

我没有SQL Server设置,但我无法使用JDK 1.7.0在Windows 7 x64上重现PostgreSQL 9.0和MySQL 5.1的问题。 因此JDK 1.7.0可以被排除在怀疑之外。 我的印象是SQL Server JDBC驱动程序应该归咎于此。 我建议改用jTDS JDBC驱动程序。 与MS提供的SQL Server JDBC驱动程序相比,它一直受到称赞,因为它具有更好的性能和稳定性。

可以在此处找到Microsoft支持部门的信息和下载链接:

http://support.microsoft.com/kb/2652061

我遇到了同样的问题,日期将关闭两天,这个热点修复了它。

这也是OpenJDK 1.6.0_20中的一个问题。 但是,mssql驱动程序适用于Suns JRE 1.6.0_16。