nik*_*eee 7 java spring cql cassandra spring-data-cassandra
添加新列时,数据库 (Cassandra) 不允许指定默认值。因此null,每一行都有新的列。
现在,我们为实体添加了一个标志(将来可能会获得更多条目):
enum UsageFlag {
OTHER,
SPECIAL_VALUE,
}
Run Code Online (Sandbox Code Playgroud)
我们还添加了一个 ReadingConverter:
@ReadingConverter
public class UsageFlagReadingConverter implements Converter<String, UsageFlag> {
@Nonnull
@Override
public UsageFlag convert(String source) {
return source == null
? UsageFlag.OTHER
: UsageFlag.valueOf(source);
}
}
Run Code Online (Sandbox Code Playgroud)
它应该基本上把null如UsageFlag.OTHER在分析任何其他非空值作为枚举成员。
但是,这不起作用,因为根据 Spring 文档,只有在值不是时才会调用Converter的convert 方法。因此,如果该实体在数据库中,则该实体的字段仍然存在。如果(且仅当)有值时,它才能正常工作。由于整个列在创建时为空,这完全违背了. nullnullnullReadingConverter
Cassandra 似乎不支持为每一行设置一个值(如UPDATE foo SET flag='OTHER' WHERE True),所以这似乎是一个不错的选择。我们希望避免手动接触数据库中的每一行。
在这种情况下,我们有什么方法可以使用 Spring 来提供帮助吗?或者有没有办法使用 CQL 或 Cassandra 解决这个问题?
编辑:有关设置的更多上下文:
public interface FancyEntityRepository extends MapIdCassandraRepository<FancyEntity> {
}
public class FancyEntity {
@PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private string id;
private UsageFlag usage;
// other columns omitted
// getters and setter omitted for this example
}
// Somewhere in a service:
FancyEntity fe = fancyEntityRepository.findOne("1");
System.out.println(fe.getUsage());
Run Code Online (Sandbox Code Playgroud)
但我不认为转换器的行为是特定于 cassandra 的。
该表已创建,然后以这种方式更改:
CREATE TABLE FancyEntity (
id TEXT,
-- other columns omitted
PRIMARY KEY (id)
);
ALTER TABLE FancyEntity ADD (
usage TEXT
);
Run Code Online (Sandbox Code Playgroud)
关于 ALTER TABLE 的 Cassandra Docs和有关使用默认值更改表的相关 SO 问题。
Cassandra 具有稀疏存储,这意味着如果未设置列(RDBMS 中的字段),它不会存储列。因此,说“新列是null”是不正确的。
如果您使用准备好的语句,则需要BoundStatement.unset()使用本机协议 v3 进行调用,以便不会为null值生成逻辑删除。
否则,可以不使用本机协议 v4(Cassandra 2.2 或更高版本)设置变量。干杯!