我通过设置对postgres的时间戳绑定来面对这似乎是一个着名的问题。
@Test
public void testGetCurrentDate() {
NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(datasources.get(dbType));
PlatformTransactionManager manager = new DataSourceTransactionManager(datasources.get(dbType));
final Timestamp ts = new Timestamp(System
.currentTimeMillis());
new TransactionTemplate(manager).execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
template.update("create table test_timestamp (col timestamp)", Collections.emptyMap());
template.update("insert into test_timestamp (col) values (:TS) ", Collections.singletonMap("TS", ts));
}
});
Assert.assertEquals((Integer) 1, new TransactionTemplate(manager).execute(new TransactionCallback<Integer>() {
@Override
public Integer doInTransaction(TransactionStatus status) {
MapSqlParameterSource paramsSource = new MapSqlParameterSource();
paramsSource.addValue("TS", ts, Types.TIMESTAMP, "timestamp");
return template.queryForObject("select 1 from test_timestamp where :TS is not null and col=:TS ", paramsSource,
Integer.class);
}
}));
}
此测试失败,错误:无法确定参数$ 1的数据类型
在这里看到与postgres有关的讨论: http://www.postgresql-archive.org/quot-could-not-determine-data-type-of-parameter-quot-with-timestamp-td5995489.html
我已经有了解决方法(设置PGTimestamp实例而不是Timestamp)。我想知道它是否有助于Spring JDBC提高多个数据库的可移植性。
在这种情况下,org.springframework.jdbc.core.StatementCreatorUtils(第380行附近)的解决方法是这样的:
else if (sqlType == Types.TIMESTAMP &&
"PostgreSQL".equals(ps.getConnection().getMetaData().getDatabaseProductName()))) {
Class<?> pgTimestampClass = Class.forName("org.postgresql.util.PGTimestamp");
Timestamp ts = (Timestamp)pgTimestampClass.getConstructor(long.class).newInstance(javaValue.getTime());
ps.setTimestamp(paramIndex, ts);
如果您认为它有意义,我可以提出拉取请求。
Arnaud