【问题标题】:Cassandra Java Driver get TypeCodec for Java typeCassandra Java Driver 获取 Java 类型的 TypeCodec
【发布时间】:2017-05-22 17:16:33
【问题描述】:

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

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

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

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

Cassandra 的CodecRegistry 类提供了方法:

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);

问题是,这些方法都不适合我的用例。几乎所有方法都需要DatatType cqlTypeparameter,我无法提供,因为我没有找到将给定的keyType 类文字映射到可能匹配的Cassandra Datatype 的方法。 (这可能吗?)

我想要的唯一接近的是: public &lt;T&gt; TypeCodec&lt;T&gt; codecFor(T value); 但它需要类的 instance 而不是类文字。 所以我想要的是:

public &lt;T&gt; TypeCodec&lt;T&gt; codecFor(Class&lt;T&gt; javaType);

这将为我提供用于给定类型的默认 TypeCodec,即如果我传入类型“java.lang.Integer”,则应返回对应的 cassandra TypeCodec for Integers。

对如何实现此行为有何建议?

【问题讨论】:

    标签: java cassandra datastax-java-driver


    【解决方案1】:

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

    同时,我建议你重新设计你的createStore 方法;您的应用程序可能知道——或者至少应该知道——对于给定的keyType 使用什么 CQL 类型。不知道使用哪种 CQL 类型通常很糟糕。

    【讨论】:

      【解决方案2】:

      CodecRegistry 类有两个字段存储所有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));
      

      【讨论】:

      • 谢谢,我认为这可行。我不确定我是否要依赖反射。你有什么其他方法可以实现我想要的吗?
      • 我已经搜索过他们的api,没有找到其他方法。实际上他们不需要那样的人。
      • 或者你可以硬编码一个地图,用于所有类型编解码器
      猜你喜欢
      • 2021-02-13
      • 2016-02-26
      • 1970-01-01
      • 2020-10-20
      • 2018-01-02
      • 2022-01-06
      • 2016-07-25
      • 1970-01-01
      • 2017-02-13
      相关资源
      最近更新 更多