26

我正在使用 Java JDBC 将日期写入 SQL Server 2008,然后将其读回。
回读的日期始终比实际写入的日期早两天。

我正在使用准备好的语句插入包含日期字段的行。日期值由以下提供:

java.sql.Date todaysDate = new java.sql.Date(System.currentTimeMillis()) ;
System.out.println(todaysDate.toString()) // -> 2012-07-02
ps.setDate(8, todaysDate);

将日期写入数据库后,如果我运行,SQL 服务器会显示正确的日期:

select date from table_name where date!=null // ->2012-07-02

如果我通过 JDBC 运行相同的查询,则使用从结果集中检索日期值

java.sql.Date sqlDate = rs.getDate("date") ;
sqlDate.toString() // ->2012-06-30

插入的行是表中唯一具有非空日期的行,因此这似乎不是读取错误记录的情况。

我认为这将是一个众所周知的问题,但我可以通过谷歌搜索“两天假”问题找到的唯一参考没有明确的答案。

有任何想法吗?

beeky(生活在过去)

4

9 回答 9

22

错误的 JDBC 驱动程序

原来问题出在 MS JDBC 驱动程序上。我尝试了日期类型和日期转换的所有可能组合,但没有任何效果。经过大量搜索(应该先这样做!)我看到一个对旧 SO 条目的评论,暗示问题是来自 Microsoft 的版本 3 JDBC 驱动程序。我得到了最新的驱动程序,版本 4.something,问题就消失了。

感谢所有试图提供帮助的人。特别感谢迈克花时间发布解决方案。

-=笨拙

于 2012-07-12T13:11:47.680 回答
5

对于那些使用 maven 的人,将其用于 java 8:

 <dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>6.2.1.jre8</version>
 </dependency>

如前所述,如果您使用旧版本,您可能会遇到这个问题,并且不容易调试。

于 2017-07-27T15:44:08.810 回答
2

我最近遇到过几次这个问题,并且在记住如果字段的类型为 date 时会发生这种情况,将字段类型切换为 datetime 类型可以解决问题。

于 2015-05-11T12:41:47.980 回答
2

就像user903724所说的那样,更改为可以修复的版本4,但在我的情况下,当我使用sqljdbc4-3.0.jar时,这个问题仍然存在,但我将其更改为sqljdbc42.jar,这个问题得到了修复。希望我的经验会有所帮助。从sqljdbc42.jar下载

于 2016-04-11T15:24:13.233 回答
2

如果您使用的是 MSSQL 2015,请使用此Sqljdbc41修复此问题

 <!-- https://mvnrepository.com/artifact/com.microsoft.sqlserver/sqljdbc41 -->
<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>sqljdbc41</artifactId>
    <version>6.0.8112</version>
</dependency>
于 2018-10-12T06:09:36.883 回答
1

当我们在 Microsoft sql 中使用日期数据类型时,就会出现这个问题。我已修复此问题以将日期更改为日期时间。

于 2018-04-12T12:39:44.600 回答
0

我有完全相同的问题。一旦我使用 java 6 运行时环境而不是 java 7 运行时环境,2 天的偏移就消失了。

因此,JDBC 4.1 版本与 JDBC 3 驱动程序的向后兼容性也可能存在差异。

于 2013-08-27T10:06:02.303 回答
0

您的问题是时区值(“GMT”)。
您需要在JDBC获取方法中引入此操作,如下所示:

Calendar gmt = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setDate(1, new Date(0)); // I assume this is always GMT
ResultSet rs = stmt.executeQuery();
rs.next();

//This will output 0 as expected
System.out.println(rs.getDate(1, gmt).getTime());
于 2012-07-02T15:40:30.937 回答
0

即使将 sqljdbc4 与 Java 8 一起使用,我也遇到了同样的问题。

一旦我不需要这个字段在应用程序中进行任何类型的比较,我就通过在我的查询中转换字段来解决这个问题,如下所示CAST(dbo.tblPwActividadeParticipanteDetalhe.Data AS VARCHAR(10))

于 2017-04-05T06:28:07.280 回答