1

I need to store YearMonth in postgres. According to this SO answer the best postgres type is date.

Given that we use kotlin + spring-data-r2dbc, how should we implement the mapping?

With an AttributeConverter I would implement it like this:

import java.time.LocalDate
import java.time.YearMonth
import javax.persistence.AttributeConverter

class YearMonthIntegerAttributeConverter : AttributeConverter<YearMonth?, Int?> {
  fun convertToDatabaseColumn(
    attribute: YearMonth?
  ): LocalDate? {
    return attribute?.atDay(1)
  }

  fun convertToEntityAttribute(
    date: LocalDate?
  ): YearMonth? {
    if (date == null) {
      return null
    }
    return YearMonth.of(date.year, date.month)
  }
}

But using a AttributeConverter is not possible because javax.persistence is not available in this stack.

Stuck
  • 11,225
  • 11
  • 59
  • 104

1 Answers1

0

Turns out reading the docs again solves it.

The alternatives are

import org.springframework.core.convert.converter.Converter
import org.springframework.data.convert.ReadingConverter
import org.springframework.data.convert.WritingConverter

and the above example can be implemented like this:

@WritingConverter
class YearMonthToDateConverter : Converter<YearMonth, LocalDate> {
  override fun convert(source: YearMonth): LocalDate {
    return source?.atDay(1)
  }
}


@ReadingConverter
class DateToYearMonthConverter : Converter<LocalDate, YearMonth> {
  override fun convert(source: LocalDate): YearMonth {
    return YearMonth.of(source.year, source.month)
  }
}

This requires to register the converters with the r2dbc configuration AbstractR2dbcConfiguration.

@Configuration
class R2dbcConfig(
  private val connectionFactory: ConnectionFactory,
) : AbstractR2dbcConfiguration() {
  override fun connectionFactory() = connectionFactory

  override fun getCustomConverters(): List<Any> {
    return listOf<Converter<out Any, out Any>>(
      YearMonthToDateConverter(),
      DateToYearMonthConverter()

    )
  }
}
Stuck
  • 11,225
  • 11
  • 59
  • 104