java.sql.Timestamp does not save correctly into a DATETIME2(7) field as an object. It gets truncated to DATETIME.
Table Definition
CREATE TABLE TimeTest (
ID BIGINT IDENTITY(1,1) NOT NULL,
aTimestamp DATETIME2 NOT NULL,
aDate DATETIME NOT NULL,
PRIMARY KEY (ID)
);
Relavant Java Test Code
Class.forName(driver);
con = DriverManager.getConnection(url, userName, password);
System.out.println("Connected to the database.");
Timestamp t = new Timestamp(System.currentTimeMillis()); t.setNanos(1234567); System.out.println("Value of timestamp: " + t); ps = con.prepareStatement("insert into TimeTest (aTimestamp, aDate) values (?, ?)"); ps.setObject(1, t); ps.setObject(2, t); System.out.println(ps.executeUpdate() + " Row(s) updated as objects"); ps.setString(1, t.toString()); ps.setString(2, sdf.format(t)); System.out.println(ps.executeUpdate() + " Row(s) updated as strings"); ps.setTimestamp(1, t); ps.setDate(2, new java.sql.Date(t.getTime())); System.out.println(ps.executeUpdate() + " Row(s) updated as Timestamp/Date"); s = con.createStatement(); rs = s.executeQuery("select * from TimeTest"); System.out.println("Retrieved from DB: "); while(rs.next()) { System.out.print(rs.getString(1) + ", "); System.out.print(rs.getString(2) + ", "); System.out.println(rs.getString(3)); }
Java program output:
Connected to the database.
Value of timestamp: 2014-11-26 14:43:51.001234567
1 Row(s) updated as objects
1 Row(s) updated as strings
1 Row(s) updated as Timestamp/Date
Retrieved from DB:
1, 2014-11-26 14:43:51.0000000, 2014-11-26 14:43:51.0
2, 2014-11-26 14:43:51.0012346, 2014-11-26 14:43:51.0
3, 2014-11-26 14:43:51.0000000, 2014-11-26 00:00:00.0
Results from SQL Server Management Console:
ID aTimestamp aDate
1 2014-11-26 14:43:51.0000000 2014-11-26 14:43:51.000
2 2014-11-26 14:43:51.0012346 2014-11-26 14:43:51.000
3 2014-11-26 14:43:51.0000000 2014-11-26 00:00:00.000
In row 1 and 3 the java.sql.Timestamp is incorrect. Row 2 is rounding, which I can live with.
The DATETIME field is correct on all three rows.
Since I'm using Hibernate, the insert as an Object must work correctly. I'm receiving data from devices with microsecond precision; truncated milliseconds won't do, and I can't use the String insert kluge.
I am suffering from the same issue, using optimistic locking in JPA which is based on Timestamp and will not work when precision is not correct.