'How to save collection of user defined type to ScyllaDB with Spring Data Cassandra?
When I try to save entity with a list or set of user defined type, I get error:
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]]
That's the definition that is in ScyllaDB database:
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)
);
Entity in 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;
}
}
And saving to database:
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);
Using version 3.2.0
of spring-data-cassandra
Solution 1:[1]
I'm not a Spring expert (just a Scylla expert ;-)), so please forgive me if my answer doesn't work.
It seems to me that the annotation
@Column("attachments")
@CassandraType(type = CassandraType.Name.UDT, userTypeName = "attachment_info")
private Set<AttachmentInfo> attachments = new HashSet<>();
Is wrong because it tells spring-data-cassandra that the "attachments" column is a UDT, while in fact it isn't - it's a set (of UDTs).
I think that the correct annotation for a set of UDTs would be something like:
@CassandraType(type = DataType.Name.SET, typeArguments = DataType.Name.UDT)
But I'm not sure (I couldn't find an example in documentation) where to put the userTypeName. If I understand the documentation correctly, you don't need the that userTypeName explicitly because you annotated the AttachmentInfo class with a UserDefinedType annotation saying that its scylla name is "attachment_info" and that should hopefully be enough.
Moreover, according to some documentation I read, you may not need the CassandraType
annotation on attachements
at all, because spring-data-cassandra understands Set<AttachmentInfo>
because it knows the primitive type Set
, and you already annotated AttachmentInfo
as a UDT.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Nadav Har'El |