Spring项目Cassandra UDT写入报错:Cannot resolve UserDefinedType for [device_list]
问题:Spring项目操作Cassandra写入含UDT的表失败,报错
Cannot resolve UserDefinedType for [device_list] 在Spring项目中向包含UDT的Cassandra表写入数据时失败,报错信息为Cannot resolve UserDefinedType for [device_list]。
项目依赖
//cassandra implementation 'org.springframework.data:spring-data-cassandra:3.1.2' implementation 'io.projectreactor:reactor-core' implementation 'com.datastax.cassandra:cassandra-driver-core:3.10.2' implementation 'com.datastax.oss:java-driver-mapper-runtime:4.13.0' implementation 'com.datastax.oss:java-driver-core:4.13.0' implementation 'com.datastax.cassandra:cassandra-driver-mapping:3.6.0'
Java版本
java --version openjdk 11.0.18 2023-01-17 LTS OpenJDK Runtime Environment Corretto-11.0.18.10.1 (build 11.0.18+10-LTS) OpenJDK 64-Bit Server VM Corretto-11.0.18.10.1 (build 11.0.18+10-LTS, mixed mode)
实体类代码
import com.datastax.driver.core.DataType; import com.xxx.pai.gm.ws.core.model.Widgets; import java.util.List; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.data.cassandra.core.cql.Ordering; import org.springframework.data.cassandra.core.cql.PrimaryKeyType; import org.springframework.data.cassandra.core.mapping.CassandraType; import org.springframework.data.cassandra.core.mapping.Column; import org.springframework.data.cassandra.core.mapping.Frozen; import org.springframework.data.cassandra.core.mapping.PrimaryKeyColumn; import org.springframework.data.cassandra.core.mapping.Table; @Data @AllArgsConstructor @NoArgsConstructor @Table("shortcut_widgets") public class ShortcutWidgetEntity { @PrimaryKeyColumn(ordinal = 0, type = PrimaryKeyType.PARTITIONED, ordering = Ordering.ASCENDING) @Column("customerId") private String customerId; @Frozen @Column("device_list") @CassandraType(type = CassandraType.Name.LIST, userTypeName = "device_list", typeArguments = CassandraType.Name.UDT) List<Devices> deviceList; }
UDT类代码
import com.datastax.driver.mapping.annotations.Field; import com.datastax.driver.mapping.annotations.UDT; import com.xxx.pai.gm.ws.core.controller.request.ShortcutWidgets; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.data.cassandra.core.mapping.UserDefinedType; @Data @Builder @AllArgsConstructor @NoArgsConstructor @UserDefinedType("device_list") public class Devices { private Long bannerId; private String uniqueId; private String type; private String imageUrl; private String darkImageUrl; private String url; private String title; private Integer metaDataSourceId; }
Cassandra表结构
create TYPE device_list( bannerId bigint, uniqueId text, type text, imageUrl text, darkImageUrl text, url text, title text, metaDataSourceId int ); CREATE TABLE shortcut_widgets ( customerId text PRIMARY KEY, device_list frozen<list<device_list>> );
Repository代码
@Repository public class ShortcutWidgetsRepository { private static final String KEYSPACE_NAME = "shortcuts"; private final MeterRegistry meterRegistry; private final ReactiveCassandraTemplate template; public ShortcutWidgetsRepository( @Qualifier("cassandraTemplate1") ReactiveCassandraTemplate template, MeterRegistry meterRegistry) { this.template = template; this.meterRegistry = meterRegistry; } public Mono<ShortcutWidgetEntity> saveWidget(ShortcutWidgetEntity shortcutWidgetEntity) { return template.insert(shortcutWidgetEntity); } }
已尝试操作
- 调整依赖版本,但因依赖冲突无法注入Session Bean,问题未解决
- 参考相关博客内容,未找到有效解决方案
解决方案
1. 统一Cassandra驱动版本,消除依赖冲突
当前依赖混合了DataStax驱动3.x和4.x版本,这是核心问题。Spring Data Cassandra 3.1.2对应DataStax OSS驱动4.x系列,需移除所有3.x版本驱动依赖:
修改后的依赖:
//cassandra implementation 'org.springframework.data:spring-data-cassandra:3.1.2' implementation 'io.projectreactor:reactor-core' // 仅保留4.x版本驱动 implementation 'com.datastax.oss:java-driver-core:4.13.0' implementation 'com.datastax.oss:java-driver-mapper-runtime:4.13.0'
2. 修正UDT类注解
移除DataStax 3.x的@UDT/@Field注解,使用Spring Data Cassandra的@UserDefinedType并指定对应keyspace:
import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.data.cassandra.core.mapping.UserDefinedType; @Data @Builder @AllArgsConstructor @NoArgsConstructor // 指定UDT所属的keyspace,需与创建UDT的keyspace一致 @UserDefinedType(value = "device_list", keyspace = "shortcuts") public class Devices { private Long bannerId; private String uniqueId; private String type; private String imageUrl; private String darkImageUrl; private String url; private String title; private Integer metaDataSourceId; }
3. 修正实体类中UDT集合的注解
调整@CassandraType参数配置,确保类型映射正确:
@Frozen @Column("device_list") // 对于UDT集合,typeArguments指定UDT类型,userTypeName指定Cassandra中的UDT名称 @CassandraType(type = CassandraType.Name.LIST, typeArguments = CassandraType.Name.UDT, userTypeName = "device_list") List<Devices> deviceList;
4. 确保Spring扫描到UDT类
在Cassandra配置类中指定UDT所在包路径,让Spring能识别并注册UDT类型:
import org.springframework.context.annotation.Configuration; import org.springframework.data.cassandra.config.EnableReactiveCassandraRepositories; import org.springframework.data.cassandra.repository.config.CassandraMappingContextConfiguration; @Configuration @EnableReactiveCassandraRepositories(basePackages = "com.xxx.pai.gm.ws.repository") // 指定UDT类所在包 @CassandraMappingContextConfiguration(basePackages = "com.xxx.pai.gm.ws.model.udt") public class CassandraConfig { // 可添加Cassandra连接配置,如SessionFactory等 }
5. 验证Cassandra中UDT的存在
执行以下CQL确认shortcuts keyspace下存在device_list类型:
USE shortcuts; DESCRIBE TYPE device_list;
内容的提问来源于stack exchange,提问作者Deep Kiran
相关产品推荐
相关产品推荐

