如何使用 Spring Data Cassandra 将用户定义类型的集合保存到 ScyllaDB?
How to save collection of user defined type to ScyllaDB with Spring Data Cassandra?
当我尝试使用列表或用户定义类型集保存实体时,出现错误:
Failed to convert from type [java.util.ImmutableCollections$Set12<?>] to type [com.datastax.oss.driver.api.core.data.UdtValue] for value '[scrubbed.entity.Article$AttachmentInfo@3337c2b5]'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [scrubbed.entity.Article$AttachmentInfo] to type [com.datastax.oss.driver.api.core.data.UdtValue]]
这是 ScyllaDB 数据库中的定义:
CREATE TYPE IF NOT EXISTS attachment_info (
id UUID,
fileName TEXT,
mimeType TEXT,
sizeBytes BIGINT
);
CREATE TABLE IF NOT EXISTS articles
(
id UUID,
attachments SET<frozen<attachment_info>>,
PRIMARY KEY (id)
);
Java 中的实体:
@Getter
@Setter
@Table("articles")
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
public class Article {
@PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private UUID id;
@Column("attachments")
@CassandraType(type = CassandraType.Name.UDT, userTypeName = "attachment_info")
private Set<AttachmentInfo> attachments = new HashSet<>();
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@UserDefinedType("attachment_info")
public static class AttachmentInfo {
private UUID id;
private String fileName;
private String mimeType;
private Long sizeBytes;
}
}
并保存到数据库:
var metadata = new Article.AttachmentInfo();
metadata.setFileName("Filename");
metadata.setId(UUID.randomUUID());
metadata.setMimeType("image/png");
metadata.setSizeBytes(12345L);
var article = new Article();
article.setId(UUID.randomUUID());
article.setAttachments(Set.of(metadata));
articleRepository.insert(article);
使用 spring-data-cassandra
的 3.2.0
版本
我不是 Spring 专家(只是 Scylla 专家 ;-)),所以如果我的回答不起作用,请原谅我。
在我看来注释
@Column("attachments")
@CassandraType(type = CassandraType.Name.UDT, userTypeName = "attachment_info")
private Set<AttachmentInfo> attachments = new HashSet<>();
是错误的,因为它告诉 spring-data-cassandra“附件”列是一个 UDT,而实际上它不是 - 它是一组(UDT)。
我认为一组 UDT 的正确注释应该是这样的:
@CassandraType(type = DataType.Name.SET, typeArguments = DataType.Name.UDT)
但我不确定(我无法在文档中找到示例)将 userTypeName 放在哪里。如果我对文档的理解正确,则您不需要显式使用该 userTypeName,因为您使用 UserDefinedType 注释对 AttachmentInfo class 进行了注释,说明其 scylla 名称为“attachment_info”,这应该足够了。
此外,根据我阅读的一些文档,您可能根本不需要 attachements
上的 CassandraType
注释,因为 spring-data-cassandra 理解 Set<AttachmentInfo>
因为它知道原始类型 Set
,并且您已经将 AttachmentInfo
注释为 UDT。
当我尝试使用列表或用户定义类型集保存实体时,出现错误:
Failed to convert from type [java.util.ImmutableCollections$Set12<?>] to type [com.datastax.oss.driver.api.core.data.UdtValue] for value '[scrubbed.entity.Article$AttachmentInfo@3337c2b5]'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [scrubbed.entity.Article$AttachmentInfo] to type [com.datastax.oss.driver.api.core.data.UdtValue]]
这是 ScyllaDB 数据库中的定义:
CREATE TYPE IF NOT EXISTS attachment_info (
id UUID,
fileName TEXT,
mimeType TEXT,
sizeBytes BIGINT
);
CREATE TABLE IF NOT EXISTS articles
(
id UUID,
attachments SET<frozen<attachment_info>>,
PRIMARY KEY (id)
);
Java 中的实体:
@Getter
@Setter
@Table("articles")
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
public class Article {
@PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private UUID id;
@Column("attachments")
@CassandraType(type = CassandraType.Name.UDT, userTypeName = "attachment_info")
private Set<AttachmentInfo> attachments = new HashSet<>();
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@UserDefinedType("attachment_info")
public static class AttachmentInfo {
private UUID id;
private String fileName;
private String mimeType;
private Long sizeBytes;
}
}
并保存到数据库:
var metadata = new Article.AttachmentInfo();
metadata.setFileName("Filename");
metadata.setId(UUID.randomUUID());
metadata.setMimeType("image/png");
metadata.setSizeBytes(12345L);
var article = new Article();
article.setId(UUID.randomUUID());
article.setAttachments(Set.of(metadata));
articleRepository.insert(article);
使用 spring-data-cassandra
3.2.0
版本
我不是 Spring 专家(只是 Scylla 专家 ;-)),所以如果我的回答不起作用,请原谅我。
在我看来注释
@Column("attachments")
@CassandraType(type = CassandraType.Name.UDT, userTypeName = "attachment_info")
private Set<AttachmentInfo> attachments = new HashSet<>();
是错误的,因为它告诉 spring-data-cassandra“附件”列是一个 UDT,而实际上它不是 - 它是一组(UDT)。
我认为一组 UDT 的正确注释应该是这样的:
@CassandraType(type = DataType.Name.SET, typeArguments = DataType.Name.UDT)
但我不确定(我无法在文档中找到示例)将 userTypeName 放在哪里。如果我对文档的理解正确,则您不需要显式使用该 userTypeName,因为您使用 UserDefinedType 注释对 AttachmentInfo class 进行了注释,说明其 scylla 名称为“attachment_info”,这应该足够了。
此外,根据我阅读的一些文档,您可能根本不需要 attachements
上的 CassandraType
注释,因为 spring-data-cassandra 理解 Set<AttachmentInfo>
因为它知道原始类型 Set
,并且您已经将 AttachmentInfo
注释为 UDT。