Reputation: 51829
I’m working on a Java server app which uses Spring 3 and C3P0 to access a Microsoft SQL Server 2008 R2 database, using version 3.0 of Microsoft’s JDBC 4 driver.
I have a sproc which has an input defined like so:
@modifiedAfter datetime = NULL
I’m using Spring to construct a call to this sproc.
I’m constructing a MapSqlParameterSource to contain my parameters:
MapSqlParameterSource in = new MapSqlParameterSource()
in.addValue("modifiedAfter", "2011-01-01T00:00:00", Types.TIMESTAMP)
But when I execute the call:
this.sprocCall.execute(in);
I get this:
com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed when converting date and/or time from character string
…and I have no idea why.
I’ve tried a few variations on adding the parameter, such as passing it in as a Date
, or specifying it as a VARCHAR
, or not specifying the type — none of them work.
I’m beginning to suspect that the problem might be related to Spring. I wrote a little Groovy script to try to isolate the problem, and this works just fine:
dt = new DateTime("2012-02-01T00:00:00") // Joda DateTime
println sql.rows("exec spMySproc @modifiedAfter=${Sql.TIMESTAMP(dt.toString())}")
…but when I try the equivalent approach with MapSqlParameterSource
, I get the above error.
At this point, I’m stumped.
Here’s the top of the stacktrace:
org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call spGetPoliciesCatalogPaged(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}]; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed when converting date and/or time from character string.
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:97)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:952)
at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:985)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:368)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:342)
at org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:164)
… which is followed by some of my classes, then this:
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed when converting date and/or time from character string.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:197)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet$FetchBuffer.nextRow(SQLServerResultSet.java:4762)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet.fetchBufferNext(SQLServerResultSet.java:1682)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet.next(SQLServerResultSet.java:955)
at com.mchange.v2.c3p0.impl.NewProxyResultSet.next(NewProxyResultSet.java:2859)
at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:91)
at org.springframework.jdbc.core.JdbcTemplate.processResultSet(JdbcTemplate.java:1124)
at org.springframework.jdbc.core.JdbcTemplate.extractReturnedResults(JdbcTemplate.java:1023)
at org.springframework.jdbc.core.JdbcTemplate$5.doInCallableStatement(JdbcTemplate.java:995)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:936)
... 68 more
I tried updating to the latest version of spring-jdbc
, 3.1.1, but it did not help.
I’d appreciate any help at all!
Thanks, Avi
Upvotes: 3
Views: 5823
Reputation: 833
Had a similar problem in and was looking @ MSDN and looks like Sql-Server 2005 had a bug with precision conversion. Supposedly the version you are using has bumped up the precision 100ns. Will it be possible verify if the time-stamp precision. Here is the link for the discussion: Sql Server Conversion error
Upvotes: 1
Reputation: 51829
A co-worker of mine figured this out. It turns out that I had jumped the gun by blaming Spring and/or the Microsoft SQL Server driver. The problem was indeed an error when converting a character string to a date/time — but it wasn’t a problem directly with my parameter, it was a problem with a query that was being run by the dynamic SQL generated by my sproc, if I passed in this parameter.
The problematic code looks something like this:
IF @modifiedAfter IS NOT NULL BEGIN
SET @SQL = @SQL + N'AND mytable.ThingLastUpdated > @modifiedAfter'
END
Once the dynamic SQL contained in @SQL
was actually executed, the contents of @modifiedAfter
— a perfectly valid DATETIME
, sent in from my Java code with no issues at all — were compared with the contents of mytable.ThingLastUpdated
— which was a VARCHAR
column which meant that SQL Server had to convert its contents to DATETIME
so that they could be compared to @modifiedAfter
— but not all values in mytable.ThingLastUpdated
could be successfully converted, hence the conversion error being thrown.
The fix I decided on was to change the type of mytable.ThingLastUpdated
to DATETIME
, and do any needed conversion at insertion time, which I think will be more efficient than doing so at query time.
Lesson learned: if a SQL problem isn’t in my Java code, it’s probably in my SQL — not in Spring or a JDBC driver. PEBKAC.
Upvotes: 2
Reputation: 3415
This error is defenitely not a SQL problem bacause it converts that string "2011-01-01T00:00:00" to datetime successfully. The sql parameter type you have declared is of type TIMESTAMP and you are passing a string. I think that is where it fails to convert.
Try declaring the sql parameter type as string or varchar instead of TimeStamp.
Upvotes: 1
Reputation: 523
How about passing the input as String/varchar and then converting it to datetime in the sproc?
Upvotes: 1