-
Hi team, The table looks like below. CREATE TABLE jsonb_example (
id integer NOT NULL,
name character varying(10) NOT NULL,
reported_date date NOT NULL,
measure jsonb
); I defined entity model in Kotlin like this. And I hope the measure: Measure? field is converted to json string and stored in the table correctly. @Table("jsonb_example")
data class JsonbExample (
@Id
@Column("id")
val id: Long? = null,
val name: String,
val reportedDate: LocalDate,
var measure: Measure? = null,
): Serializable { } With a repository definition. @Repository
interface JsonbExampleRepository: CoroutineCrudRepository<JsonbExample, Long> {
} The class 'Measure' contains some data. data class Measure(
@JsonProperty("Code")
val code: String,
@JsonProperty("Name")
val name: String,
@JsonProperty("Abbreviation")
val abbreviation: String,
) { } I hope the Measure object is converted to json string and stored to table correctly. @WritingConverter
class MeasureEncoder: Converter<Measure, Json?> {
private val objectMapper: ObjectMapper = ObjectMapper()
override fun convert(source: Measure): Json? {
return runCatching {
Json.of(objectMapper.writeValueAsString(source))
}.getOrNull()
}
}
@ReadingConverter
class MeasureDecoder: Converter<Json, Measure> {
private val objectMapper: ObjectMapper = ObjectMapper()
override fun convert(source: Json): Measure {
return runCatching {
objectMapper.readValue<Measure>(source.asString())
}.getOrElse { Measure.create() }
}
} And, registered the converters in R2dbcConfiguration. @Configuration
@EnableR2dbcRepositories
class R2dbcConfiguration {
companion object {
const val DRIVER_NAME = "postgresql"
}
@Bean
fun r2dbcMappingContext(
namingStrategy: ObjectProvider<NamingStrategy>,
r2dbcCustomConversions: R2dbcCustomConversions
): R2dbcMappingContext? {
val relationalMappingContext = R2dbcMappingContext(
namingStrategy.getIfAvailable { NamingStrategy.INSTANCE })
relationalMappingContext.setSimpleTypeHolder(r2dbcCustomConversions.simpleTypeHolder)
return relationalMappingContext
}
@Bean
fun r2dbcCustomConversions(): R2dbcCustomConversions {
val converters = ArrayList<Any>().apply {
addAll(PostgresDialect.INSTANCE.converters)
addAll(R2dbcCustomConversions.STORE_CONVERTERS)
add(MeasureEncoder())
add(MeasureDecoder())
}
return R2dbcCustomConversions(R2dbcCustomConversions.STORE_CONVERSIONS, converters)
}
@Bean
fun r2dbcConverter(mappingContext: R2dbcMappingContext?, r2dbcCustomConversions: R2dbcCustomConversions?) =
MappingR2dbcConverter(mappingContext!!, r2dbcCustomConversions!!)
} With above codes, when I try to save JsonbExample object using the repository, With some debugging, I figured out that the converters works fine which means Measure object is correctly converted to Json object, but at the very final stage of building insert query, the value of measure field becomes 'null' because 'Json' type is not registered in r2dbc SimpleTypeHolder and r2dbc QueryMapper doesn't have any idea of how to proceed with Json type so it makes the value 'null'. I also tried with the Converter from Measure to String type (not Json), but at this time, the query execution throws exeption like this.
How can I convert the custom data class object to jsonb column and vice versa? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
I solved the problem by adding PostgresDialect.INSTANCE.simpleTypeHolder to R2dbcCustomConversions constructor. @Configuration
@EnableR2dbcRepositories
class R2dbcConfiguration {
companion object {
const val DRIVER_NAME = "postgresql"
}
@Bean
fun r2dbcMappingContext(
namingStrategy: ObjectProvider<NamingStrategy>,
r2dbcCustomConversions: R2dbcCustomConversions
): R2dbcMappingContext? {
val relationalMappingContext = R2dbcMappingContext(
namingStrategy.getIfAvailable { NamingStrategy.INSTANCE })
relationalMappingContext.setSimpleTypeHolder(r2dbcCustomConversions.simpleTypeHolder)
return relationalMappingContext
}
@Bean
fun r2dbcCustomConversions(): R2dbcCustomConversions {
val converters = ArrayList<Any>().apply {
addAll(PostgresDialect.INSTANCE.converters)
addAll(R2dbcCustomConversions.STORE_CONVERTERS)
add(JsonToMapReadConverter())
add(MapToJsonWriteConverter())
add(MeasureEncoder())
add(MeasureDecoder())
}
return R2dbcCustomConversions(
StoreConversions.of(
PostgresDialect.INSTANCE.simpleTypeHolder, // <- this contains Json class object as simple type
R2dbcCustomConversions.STORE_CONVERTERS),
converters)
}
@Bean
fun r2dbcConverter(mappingContext: R2dbcMappingContext?, r2dbcCustomConversions: R2dbcCustomConversions?) =
MappingR2dbcConverter(mappingContext!!, r2dbcCustomConversions!!)
|
Beta Was this translation helpful? Give feedback.
I solved the problem by adding PostgresDialect.INSTANCE.simpleTypeHolder to R2dbcCustomConversions constructor.