我需要让我的 kotlin 实体字段 (
String
) 与 DB 列 BIGINT
正常工作。我相信我可以使用 spring data converters 来实现它,但我找不到示例或文档。有人可以解释一下如何使用@WritingConverter和@ReadingConverter吗?
如果没有转换器,我在保存/获取操作时不断收到此类错误:
PostgresqlBadGrammarException: operator does not exist: bigint = character varying
UPD 我设法配置自定义转换器:
@Configuration
@EnableR2dbcRepositories
class R2dbcConfiguration {
@Bean
fun r2dbcCustomConversions(
stringToBigIntConverter: StringToBigIntConverter,
bigIntToStringConverter: BigIntToStringConverter
): R2dbcCustomConversions {
return R2dbcCustomConversions(listOf(stringToBigIntConverter, bigIntToStringConverter))
}
}
自定义转换器:
@Component
@WritingConverter
class BigIntToStringConverter: Converter<Long, String> {
override fun convert(source: Long): String {
return source.toString()
}
@Component
@WritingConverter
class StringToBigIntConverter: Converter<String, Long> {
override fun convert(source: String): Long {
return source.toLong()
}
}
但现在它尝试将每个 String 字段转换为 BIGINT,反之亦然。如何仅将转换器应用于特定实体的特定字段?
首先,我很惊讶没有从 Postgres BIGINT 到类似
java.math.BigInteger
的映射。但是让我们继续你的问题,我假设你想使用 Java/Kotlin Long
并将其作为字符串序列化到数据库。
其次,我认为应该定义 1
WritingConverter
和 1 ReadingConverter
,你有 2 x WritingConverter
。
这是我在 Kotlin 端的一个名为
RULID
的特殊类型的工作代码,我们的 MongoDB 不知道如何处理,因此我们定义了一对用于读/写的转换器:
@ReadingConverter
class DBObjectToRULIDConverter : Converter<String, RULID> {
override fun convert(source: String): RULID {
if (!RULID.isValid(source)) {
return RULID.INVALID
}
return RULID.from(source)
}
}
@WritingConverter
class RULIDToDBObjectConverter : Converter<RULID, String> {
override fun convert(source: RULID): String {
val h : BigInteger
return source.toString()
}
}
因此,
ReadingConvertor
是从数据库中获取字符串并转换为RULID
,而WritingConverter
则是获取RULID并转换为准备持久化的String
。因此,您需要根据您的情况更改 RULID
-> Long
。
第三,你问“如何才能只针对特定实体的特定字段应用转换器?”
根据2021年的答案:https://stackoverflow.com/a/69614213/1847378
您当前无法在 Spring Data 中定义特定于字段的转换器(JDBC 或其他)。
我认为你可以通过使用 Kotlin 类型别名来解决这个问题:
typealias BigInt = Long
然后你的转换器:
@Component
@WritingConverter
class BigIntToStringConverter: Converter<BigInt, String> {
...etc