spring-projects / spring-projects/spring-data-relational

Same type (java.sql.Timestamp) turns into different SQL-types

Open
#1,089 11 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: feedback-provided theme: date-time
Dominant language
Java
Stars
827
Forks
394
PR merge metrics
No merged PRs in 30d

Description

Hello, I am not sure where this happens, but I am having some trouble with ZonedDateTime.

I have read in the documentation that ZonedDateTime is not supported (https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#jdbc.entity-persistence.types), therefore I wrote a converter (ZonedDateTime -> java.sql.Timestamp).

I have the following data class:

data class OrderLineEvent(
  (...) other fields 
  val orderLineEventType: String? = null,
  val travelDate: ZonedDateTime? = null, 
  val timestamp:  LocalDateTime = LocalDateTime.now() // Actually a ZonedDateTime, but using LocalDateTime for illustration purposes 
) {
}

Converter:

import java.sql.Timestamp
import java.time.ZoneOffset
import java.time.ZonedDateTime

@Configuration
@EnableJdbcRepositories
class DataJdbcConfiguration : AbstractJdbcConfiguration() {

  @WritingConverter
  class ZonedDateTimeWriterConverter : Converter<ZonedDateTime, Timestamp> {

    override fun convert(date: ZonedDateTime): Timestamp {
      return Timestamp.valueOf(date.withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime())
    }

  }

  @Bean
  override fun jdbcCustomConversions(): JdbcCustomConversions {
    return JdbcCustomConversions(listOf(ZonedDateTimeWriterConverter()))
  }
}

Repository:

@Repository
interface OrderLineEventRepository : CrudRepository<OrderLineEvent, Long>

Ok, here is the issue: I am unable to save this as a timestamp. The error is Translating SQLException with SQL state '42804', error code '0', message [ERROR: column "travel_date" is of type timestamp without time zone but expression is of type character varying which is quite odd.

After investigating this further (and enabling TRACE-logging), it seems like the parameter gets converted into a VARCHAR/string type(?) AND a different type than the `LocalDateTime

Look at logs below:

o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 11, parameter value [123.42], value class [java.lang.String], SQL type 12  
o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 12, parameter value [2021-11-17 08:31:28.731541], value class [java.sql.Timestamp], SQL type 93  
o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 13, parameter value [2021-11-17 08:31:28.73009], value class [java.sql.Timestamp], SQL type 12  

It seems like String and ZonedDateTime turns into the same SQL type.

String -> java.lang.String, SQL type 12
LocalDateTime -> java.sql.Timestamp, SQL type 93
ZonedDateTime -> java.sql.Timestamp, SQL type 12

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the ZonedDateTimeWriterConverter in DataJdbcConfiguration and trace the parameter handling shown by StatementCreatorUtils. Reproduce the OrderLineEvent save and compare the logged SQL types for ZonedDateTime and LocalDateTime; done means the converted ZonedDateTime binds as a timestamp without time zone rather than as a VARCHAR.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
backend, database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.