【问题标题】:Datastax Object Mapper: change table on the flyDatastax 对象映射器:动态更改表
【发布时间】:2017-01-22 17:24:10
【问题描述】:

我需要即时更改我的映射注释指向的表。考虑以下内容:

@Table(name="measurementtable_one", keyspace="mykeyspace")
public class Measurement {/*...*/}

我有多个表,其命名模式为“measurementtable_*”,其名称在编译时不一定已知,而我需要使用的表是由程序的输入选择的。由于所有这些表都是相同的,我不想为每个表创建一个新类;而且我不想为每个输入重新编译我的程序。

有没有办法保留对象映射功能而不必在注释中指定我的确切表名?

【问题讨论】:

    标签: java cassandra datastax


    【解决方案1】:

    通过常规方式,没有。由于注释实际上是常量,因此您无法通过常规方式更改它们。由于 Datastax 对象映射器没有公开任何方式来动态切换映射对象的表,因此必须采用更黑暗的艺术:字节码操作。

    虽然可以直接操纵Measurement 的注释,但我不喜欢更改应该 保持不变的内容。因此,Measurement 类应该失去其注释并被抽象化:

    public class Measurement { /*...*/ }
    

    然后,一旦知道了真实的表名,就可以使用 javassist 生成带有正确注释的子类:

    String modelname = getNameFromExternalSource(); //Replace with real external source.
    String modelcleanname = modeldir.getName().replaceAll("\\W", "");
    ClassPool pool = ClassPool.getDefault();
    String measurementclassname = "measurementtable_" + modelcleanname;
    CtClass stagingmeasurementclass = pool.makeClass(measurementclassname);
    stagingmeasurementclass.setSuperclass(pool.get(StagingMeasurementRecord.class.getName()));
    stagingmeasurementclass.setModifiers(Modifier.PUBLIC);
    ClassFile stagingmeasurementclassfile = stagingmeasurementclass.getClassFile();
    ConstPool constpool = stagingmeasurementclassfile.getConstPool();
    AnnotationsAttribute attribute = new AnnotationsAttribute(constpool,
            AnnotationsAttribute.visibleTag);
    Annotation tableannotation = new Annotation(constpool, pool.get(Table.class.getName()));
    tableannotation.addMemberValue("name", new StringMemberValue(measurementclassname, constpool));
    tableannotation.addMemberValue("keyspace", new StringMemberValue("mykeyspace", constpool));
    attribute.addAnnotation(tableannotation);
    stagingmeasurementclassfile.addAttribute(attribute);
    stagingmeasurementclass.addConstructor(
            CtNewConstructor.make(new CtClass[0], new CtClass[0], stagingmeasurementclass));
    Class<? super StagingMeasurementRecord> myoutputclass = stagingmeasurementclass.toClass();
    LOGGER.info("Created custom measurementtable class with the name " + myoutputclass.getName());
    

    然后,您可以将 myoutputclass 实例提供给 MappingManagerInstance.mapper(...) 调用,以生成指向所需表的对象映射器。

    考虑到字节码操作是必要的,它并不是最漂亮的解决方案,但它可以完成它需要做的事情,同时避免为每个输入重新编译或为您的对象创建一百万个相同的类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-02
      • 2016-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-03
      • 2021-10-28
      • 1970-01-01
      相关资源
      最近更新 更多