Spring Boot操作Apache Cassandra遇ConverterNotFoundException求助
解决Spring Data Cassandra中EventMetadata转UdtValue的ConverterNotFoundException异常
异常概述
在Spring Boot应用向Cassandra保存数据时触发如下转换异常:
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [com.xxxxx.scenario.model.entity.EventMetadata] to type [com.datastax.oss.driver.api.core.data.UdtValue] at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:322) ~[spring-core-5.3.22.jar!/:5.3.22] ... 后续栈帧省略
原因分析
- 主实体类中EventMetadata字段未正确配置UDT映射:你只提供了
ScenarioCalculatedValues字段的注解配置,但异常指向的是EventMetadata,说明包含EventMetadata的主实体类对应字段缺少@CassandraType注解,或者注解参数与UDT定义不匹配。 - 嵌套类型
Reason无对应转换器:EventMetadata中的Set<Reason>字段,若Reason是自定义UDT或枚举类型,Spring Data Cassandra无法自动识别,需手动提供转换逻辑。 - UDT类未被Spring扫描到:
EventMetadata所在包未被Spring Data Cassandra的扫描范围覆盖,导致自动转换器无法生成。
解决办法
1. 为主实体类的EventMetadata字段添加正确注解
找到包含EventMetadata的主实体类,给对应字段添加@CassandraType注解,确保userTypeName与EventMetadata类上的@UserDefinedType值完全一致(注意Cassandra UDT名称大小写敏感):
@CassandraType(type = CassandraType.Name.UDT, userTypeName = "metadata_response") @Column("event_metadata") // 替换为实际列名 private EventMetadata eventMetadata;
2. 处理Reason类型的转换
若Reason是枚举类型
创建双向转换器并注册到Spring的转换服务:
// 枚举转String @Component public class ReasonToStringConverter implements Converter<Reason, String> { @Override public String convert(Reason source) { return source.name(); } } // String转枚举 @Component public class StringToReasonConverter implements Converter<String, Reason> { @Override public Reason convert(String source) { return Reason.valueOf(source); } }
在Cassandra配置类中注册这些转换器:
@Configuration @EnableCassandraRepositories(basePackages = "com.xxxxx.scenario.repository") public class CassandraConfig extends AbstractCassandraConfiguration { // 省略其他配置(如contactPoints、keyspaceName等) @Override public CustomConversions customConversions() { return new CustomConversions(Arrays.asList( new ReasonToStringConverter(), new StringToReasonConverter() )); } }
若Reason是UDT类型
给Reason类添加@UserDefinedType注解,并配置字段的@Column映射:
@UserDefinedType("reason_type") // 对应Cassandra中的UDT名称 @Data @AllArgsConstructor @NoArgsConstructor @Builder public class Reason { @Column("code") private String code; @Column("message") private String message; }
同时在EventMetadata的reasons字段上添加@CassandraType注解,指定集合类型和元素的UDT信息:
@CassandraType(type = CassandraType.Name.SET, typeArguments = {CassandraType.Name.UDT}, userTypeName = "reason_type") @Column("reasons") private Set<Reason> reasons = Sets.newHashSet();
3. 确保UDT类被Spring扫描覆盖
检查Cassandra配置类的扫描范围,确保包含EventMetadata、ScenarioCalculatedValues等实体类所在的包:
@Configuration @EnableCassandraRepositories(basePackages = { "com.xxxxx.scenario.repository", // 仓库包 "com.xxxxx.scenario.model.entity" // UDT实体所在包 }) public class CassandraConfig extends AbstractCassandraConfiguration { @Override protected String[] getEntityBasePackages() { return new String[]{"com.xxxxx.scenario.model.entity"}; } // 其他配置... }
4. 验证Cassandra端UDT定义匹配
确认Cassandra中metadata_response的UDT定义与EventMetadata实体类字段完全一致,例如:
CREATE TYPE metadata_response ( event_source text, reasons set<frozen<reason_type>> -- 若Reason是UDT,需用frozen );
内容的提问来源于stack exchange,提问作者Prasanna Veeramani
相关产品推荐
相关产品推荐

