Spring Boot R2DBC 自定义枚举读取转换器未生效问题:如何将数据库字符串转换为枚举类
Spring Boot R2DBC 自定义枚举读取转换器未生效问题:如何将数据库字符串转换为枚举类
嗨,我帮你分析下这个问题:你遇到的报错java.lang.IllegalArgumentException: No enum constant Gender.diverse其实已经提示了核心原因——R2DBC默认的枚举读取逻辑在干活,而你的自定义转换器根本没被调用。
默认情况下,R2DBC会给枚举类型自动注册一个默认的读取转换器,它的逻辑是直接用Enum.valueOf()去匹配枚举的名称(也就是你定义的DIVERSE、MALE这些大写常量名),但你的数据库里存的是小写的diverse,自然匹配失败。而之所以你的自定义GenderReadingConverter没生效,是因为默认转换器的优先级比你自定义的更高。
下面给你几个可行的解决方案:
方案一:全局替换默认枚举转换器
修改你的R2dbcConfig配置类,在构建R2dbcCustomConversions时,过滤掉默认的枚举相关转换器,只保留你的自定义转换器和其他必要的默认转换器:
@Configuration class R2dbcConfig( private val connectionFactory: ConnectionFactory ): AbstractR2dbcConfiguration() { override fun connectionFactory(): ConnectionFactory = connectionFactory @Bean override fun r2dbcCustomConversions(): R2dbcCustomConversions { val storeConversions = StoreConversions.of(DEFAULT_R2DBC_MAPPING_CONTEXT, emptyList()) // 初始化自定义转换器列表 val customConverters = mutableListOf( GenderReadingConverter(), GenderWritingConverter() ) // 过滤掉默认的枚举转换器,避免和自定义逻辑冲突 val filteredDefaultConverters = R2dbcCustomConversions.DEFAULT_CONVERTERS.filter { converter -> !converter.javaClass.name.contains("Enum") } // 合并自定义转换器和过滤后的默认转换器 customConverters.addAll(filteredDefaultConverters) return R2dbcCustomConversions(storeConversions, customConverters) } }
这样配置后,R2DBC就会优先使用你自定义的转换器来处理Gender枚举的读写了。
方案二:在字段上明确指定转换器(更直观)
如果你不想全局修改转换器配置,可以直接在User类的gender字段上用@Convert注解明确指定要使用的转换器,强制绕过默认逻辑:
@Table(name = "users") class User ( @Column("gender") @Convert(converter = GenderReadingConverter::class) @Convert(converter = GenderWritingConverter::class) var gender: Gender = Gender.DIVERSE, // 其他字段... ): BaseEntity()
这种方式的好处是针对性强,不会影响其他枚举类型的默认转换逻辑。
额外检查点
最后再帮你排查几个可能的小问题:
- 确保你的
GenderReadingConverter和GenderWritingConverter类上的@ReadingConverter、@WritingConverter注解没有拼写错误; - 确认你的
R2dbcConfig类被Spring正确扫描到了(比如所在包在@SpringBootApplication的扫描范围内,或者手动添加了@ComponentScan); - 验证数据库里存储的gender值确实是和枚举的
value属性一致的小写字符串(比如male、diverse)。
按照上面的方法调整后,应该就能正常将数据库的字符串转换为你的Gender枚举类了。
备注:内容来源于stack exchange,提问作者rangalo
相关产品推荐
相关产品推荐

