Cassandra Java 驱动程序获取 Java 类型的 TypeCodec

Cassandra Java Driver get TypeCodec for Java type

我有以下带有泛型参数的方法:

public <K> Store<K> createStore(final Class<K> keyType);

这只会在 cassandra 中为我创建一个具有给定类型的 table。

我想检查给定 keyType 是否已经有 TypeCodec 的默认实现。如果是,那么我只想使用这个编解码器,否则我将使用自己编写的通用编解码器。

Cassandra 的 CodecRegistry class 提供了方法:

public <T> TypeCodec<T> codecFor(DataType cqlType, Class<T> javaType);
public <T> TypeCodec<T> codecFor(DataType cqlType);
public <T> TypeCodec<T> codecFor(T value);
public <T> TypeCodec<T> codecFor(DataType cqlType, TypeToken<T> javaType);
public <T> TypeCodec<T> codecFor(DataType cqlType, T value);

事实是,none 这些方法适合我的用例。几乎所有方法都需要我无法提供的 DatatType cqlType 参数,因为我没有找到将我给定的 keyType class 文字映射到可能匹配的 Cassandra Datatype 的方法。 (这可能吗?)

唯一接近我想要的是: public <T> TypeCodec<T> codecFor(T value); 但它需要 class 的 实例 而不是 class 文字。 所以我想要的是:

public <T> TypeCodec<T> codecFor(Class<T> javaType);

这只会给我默认的 TypeCodec 用于给定类型,即如果我传入类型 "java.lang.Integer" 那么应该返回相应的整数的 cassandra TypeCodec。

有什么关于如何实现此行为的建议吗?

CodecRegistry class 有两个字段存储所有 TypeCodec

/**
 * List of Built in Codec
 */
private static final TypeCodec<?>[] BUILT_IN_CODECS;    

/**
 * The list of user-registered codecs.
 */
private final CopyOnWriteArrayList<TypeCodec<?>> codecs;

可以看到两者都是私有的。我们可以通过 java 反射

访问它们
CodecRegistry codecRegistry = CodecRegistry.DEFAULT_INSTANCE;

Map<Class, TypeCodec> javaTypeCodecMap = new HashMap<>();

try {
    Field field = codecRegistry.getClass().getDeclaredField("BUILT_IN_CODECS");
    field.setAccessible(true);
    TypeCodec<?>[] builtInCodecs = (TypeCodec<?>[]) field.get(codecRegistry);
    for (TypeCodec<?> typeCodec : builtInCodecs) {
        javaTypeCodecMap.put(typeCodec.getJavaType().getRawType(), typeCodec);
    }
} catch (NoSuchFieldException | IllegalAccessException e) {
    e.printStackTrace();
}

try {
    Field field = codecRegistry.getClass().getDeclaredField("codecs");
    field.setAccessible(true);
    CopyOnWriteArrayList<TypeCodec<?>> codecs = (CopyOnWriteArrayList<TypeCodec<?>>) field.get(codecRegistry);
    for (TypeCodec<?> typeCodec : codecs) {
        javaTypeCodecMap.put(typeCodec.getJavaType().getRawType(), typeCodec);
    }
} catch (NoSuchFieldException | IllegalAccessException e) {
    e.printStackTrace();
}

//You have the map, now you can get TypeCodec from class name
System.out.println(javaTypeCodecMap.get(String.class));

您需要的功能已被请求但尚未实现,请参阅 JAVA-1015。请为这张票投上一票并说明您希望实施它的原因。

与此同时,我建议您重新设计您的 createStore 方法;您的应用程序可能知道 – 或者至少 应该知道 – 对于给定的 keyType 使用什么 CQL 类型。不知道使用哪种 CQL 类型通常是一种难闻的气味。