【问题标题】:Cassandra Accessor / Mapper not mapping udt fieldCassandra 访问器/映射器未映射 udt 字段
【发布时间】:2017-06-27 22:40:04
【问题描述】:

我正在使用 datastax cassandra 3.1.2。我在 cassandra 中创建了下表并插入了一条记录。

CREATE TYPE memory ( capacity text );
create TABLE laptop ( id uuid primary key, model text, ram frozen<memory> );
select * from laptop ;

 id                                   | model         | ram
--------------------------------------+---------------+-------------------
 e55cba2b-0847-40d5-ad56-ae97e793dc3e | Dell Latitude | {capacity: '8gb'}

当我尝试使用 Cassandra Accessor 和以下代码从 Java 中的冻结类型内存中获取容量字段时:

this.cluster = Cluster.builder().addContactPoint(node).withPort(port).build();
session = cluster.connect();
MappingManager manager = new MappingManager(session);
LaptopAccessor laptopAccessor = manager.createAccessor(LaptopAccessor.class);
Result<Laptop> cp = laptopAccessor.getOne(UUID.fromString("e55cba2b-0847-40d5-ad56-ae97e793dc3e"));
System.out.println(cp.one());

它给内存数据点本身是空的。

id = null model = null ram = null

我期待映射器在映射时创建 ram 实例并将容量字段映射到其中并返回笔记本电脑 bean。

我有以下访问器接口:

@Accessor
interface LaptopAccessor {
   @Query("SELECT ram.capacity FROM user_info.laptop where id=?")
   Result<Laptop> getOne(UUID id);
}

上表我有以下 java bean。

@Table(keyspace = "user_info", name = "laptop")
public class Laptop {

    private UUID id;
    private String model;
    private Memory ram;

    @PartitionKey
    public UUID getId() {
        return id;
    }

    public void setId(UUID id) {
        this.id = id;
    }


    public String getModel() {
        return model;
    }


    public void setModel(String model) {
        this.model = model;
    }

    @Frozen
    public Memory getRam() {
        return ram;
    }


    public void setRam(Memory ram) {
        this.ram = ram;
    }

    @Override
    public String toString() {
        return "id = " + id + " model = " + model + " ram = " + ram;
    }

}

@UDT(keyspace = "user_info", name = "memory")
public class Memory {

    private String capacity;

    @Field
    public String getCapacity() {
        return capacity;
    }


    public void setCapacity(String capacity) {
        this.capacity = capacity;
    }

    @Override
    public String toString() {
        return "capacity = " + capacity ;
    }

}

当我更改查询以检索整个 ram UDT 时,代码工作正常。有人可以告诉我为什么当我从查询中的 udt 中选择某些字段时映射器不起作用?

cassandra 不支持这个吗?获取 UDT 字段的任何解决方法?

【问题讨论】:

    标签: datastax-java-driver cassandra-3.0


    【解决方案1】:

    我认为问题在于访问器的返回类型:

    @Accessor
    interface LaptopAccessor {
       @Query("SELECT ram.capacity FROM user_info.laptop where id=?")
       Result<Laptop> getOne(UUID id);
    }
    

    由于您的查询仅选择 ram.capacity,所有驱动程序返回的是一个包含单个列的行,该列是一个名为 ram.capacity 的 String,它不会映射到 Laptop 中的任何字段.

    相反,由于您想要的只是与该查询匹配的 1 行,因此您可以将 Accessor 更改为:

    @Accessor
    interface LaptopAccessor {
       @Query("SELECT ram.capacity FROM user_info.laptop where id=?")
       ResultSet getOne(UUID id);
    }
    

    访问器现在返回一个ResultSet,您可以为其调用one().getString(0) 来取回容量。如果您不想直接处理ResultSet,这并不理想,但效果很好。

    您不应该真的需要整个 Laptop 对象,因为您所请求的只是 UDT 的一个字段,对吧?

    【讨论】:

    • 感谢您的回答,但是,我的访问器返回类型是通用的,我在接口中还有一些其他查询,它们返回完整的笔记本电脑对象并通过我的 fetcher 部分(这是异步的)。我总是收集像 Collection results = results.add(future.get().one());因此,我认为直接在 ResultSet 上工作在我的情况下不起作用,特别是当我有多个此类查询以仅返回具有多种数据类型的 UDT 字段时。
    • 我计划在表级别移动所有此类字段(我想从 udt 中检索)或在表级别(容量)定义一个占位符,以便我可以触发查询,例如 'SELECT ram.capacity作为容量 FROM user_info.laptop where id=?'
    • 如果我有以下表结构: CREATE TABLE user_info.employees_with_address (id uuid PRIMARY KEY, complete_address list>) 如果我使用普通查询获取完整地址,那么我需要执行类似的操作下面来解析嵌套列表 Frozen UDT。行 r = rsf.get().one(); r.getList(r.getColumnDefinitions().getName(), CompleteAddress.class);如果我想让它通用,那么如何使用 Definition 获取 CompleteAddress.class 类型?
    猜你喜欢
    • 2016-10-02
    • 2018-05-06
    • 2016-01-31
    • 2013-06-09
    • 2021-01-02
    • 2022-08-03
    • 1970-01-01
    • 1970-01-01
    • 2020-08-02
    相关资源
    最近更新 更多