我已经使用 PartitionKey 注释声明了主键,但仍然得到 Entity Order 没有声明主键

Posted

技术标签:

【中文标题】我已经使用 PartitionKey 注释声明了主键,但仍然得到 Entity Order 没有声明主键【英文标题】:I have declared primary using PartitionKey annotation but still getting Entity Order does not declare a primary key 【发布时间】:2020-11-16 21:28:22 【问题描述】:

我有以下 POJO:

@Entity
public class Order     
    
    @Column(name = "id")
    @PartitionKey
    private String id;

    @Column(name = "customer_id")
    private String customerId;

    @Column(name = "loyalty_id")
    private String loyaltyId;

    @Column(name = "customer_email")
    private String customerEmail;

    public Order() 

    
    public String getId() 
       return id;
    

    public void setId(String id) 
        this.id = id;
    
    ... getters and setters

在以下代码中获取异常:

            CqlSession session = CqlSession.builder().build();
            OrderMapper mapper = new OrderMapperBuilder(session).build();
            orderDao = mapper.orderDao(CqlIdentifier.fromCql(connectionManager.getSession().getLoggedKeyspace()));

connectionManager的定义在这里:https://pastebin.com/b3GKJuV6

例外情况如下:

    Entity Order does not declare a primary key
    com.datastax.oss.driver.api.mapper.MapperException: Entity Order does not declare a primary key
        at com.datastax.oss.driver.api.mapper.MapperException.copy(MapperException.java:44)
        at com.datastax.oss.driver.internal.core.util.concurrent.CompletableFutures.getUninterruptibly(CompletableFutures.java:149)
    ...

我正在按照此处的文档进行实施:https://docs.datastax.com/en/developer/java-driver/4.2/manual/mapper/。这可能是什么原因?

编辑:- 添加架构定义:

    CREATE TABLE order_keyspace.order (
        id text PRIMARY KEY,
        customer_email text,
        customer_id text,
        loyalty_id text
    ) WITH bloom_filter_fp_chance = 0.01
        AND caching = 'keys': 'ALL', 'rows_per_partition': 'NONE'
        AND comment = ''
        AND compaction = 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'
        AND compression = 'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'
        AND crc_check_chance = 1.0
        AND dclocal_read_repair_chance = 0.1
        AND default_time_to_live = 0
        AND gc_grace_seconds = 864000
        AND max_index_interval = 2048
        AND memtable_flush_period_in_ms = 0
        AND min_index_interval = 128
        AND read_repair_chance = 0.0
        AND speculative_retry = '99PERCENTILE';

【问题讨论】:

你的keyspace也叫order吗? mapper.orderDao(CqlIdentifier.fromCql("order"));似乎表明它是,但只是想仔细检查。 @Andrew 是的,仅此而已。我也尝试过使用 session 中的 loggedKeySpace。 @Andrew 我有一个名为 ConnectionManager 的类,如下所示:pastebin.com/b3GKJuV6 和另一个名为 OrderRepositoryService 的类,其中连接管理器用作:pastebin.com/8gnWr149 【参考方案1】:

完整编辑:

这里发生了一些让我感到困惑的事情,我可以重现错误的唯一方法是破坏 getter/setter,这在您的代码中似乎没有错,但是有一些复制/粘贴正在发生的转换。到目前为止,我可以看到如下:

@Column(name = "id") 的使用 - 这不是来自 com.datastax.oss.driver.api.mapper.annotations 的注释。应该使用@CqlName。 对表使用保留关键字 - 术语“订单”是保留关键字,我很确定这会在代码中造成相当大的混乱 - 尽管当我尝试将关键字用作映射器的表名。我认为您应该将此表命名为其他名称并避免使用关键字。

注释链接: https://docs.datastax.com/en/developer/java-driver/4.2/manual/mapper/entities/ 包含可用的规则/注释,如果与命名约定不同,您可以看到 @CqlName 的使用通知映射器 Cassandra 列名称。

我相信您在之前的问题中使用的是 4.2 驱动程序 - 但如果更新到 4.7(推荐),那么这是链接:https://docs.datastax.com/en/developer/java-driver/4.7/manual/mapper/entities/)

以下代码运行正常:

Cql:

CREATE TABLE customer_orders (
    id text PRIMARY KEY,
    customer_email text,
    customer_id text,
    loyalty_id text
);

insert into customer_orders (id, customer_email, customer_id, loyalty_id) values ('a','a@b.c.com', '1234', '5678');

波乔:

import com.datastax.oss.driver.api.mapper.annotations.CqlName;
import com.datastax.oss.driver.api.mapper.annotations.Entity;
import com.datastax.oss.driver.api.mapper.annotations.PartitionKey;

@Entity
public class CustomerOrders 
    @CqlName("id")
    @PartitionKey
    private String id;

    @CqlName("customer_id")
    private String customerId;

    @CqlName("loyalty_id")
    private String loyaltyId;

    @CqlName("customer_email")
    private String customerEmail;

    public CustomerOrders() 

    

    public String getId() 
        return id;
    

    public void setId(String id) 
        this.id = id;
    

    public String getCustomerId() 
        return customerId;
    

    public void setCustomerId(String customerId) 
        this.customerId = customerId;
    

    public String getLoyaltyId() 
        return loyaltyId;
    

    public void setLoyaltyId(String loyaltyId) 
        this.loyaltyId = loyaltyId;
    

    public String getCustomerEmail() 
        return customerEmail;
    

    public void setCustomerEmail(String customerEmail) 
        this.customerEmail = customerEmail;
    

道映射器:

import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.mapper.annotations.*;

@Mapper
public interface DaoMapper 

    @DaoFactory
    OrderDao orderDao(@DaoKeyspace CqlIdentifier keyspace);

OrderDao:

import com.datastax.oss.driver.api.mapper.annotations.Dao;
import com.datastax.oss.driver.api.mapper.annotations.Delete;
import com.datastax.oss.driver.api.mapper.annotations.Insert;
import com.datastax.oss.driver.api.mapper.annotations.Select;

@Dao
public interface OrderDao 

    @Select
    CustomerOrders findById(String id);

    @Insert
    void save(CustomerOrders order);

    @Delete
    void delete(CustomerOrders order);

然后我创建了一个简单的测试sn-p:

 @Test
    void GetRecordViaOrderDao() 
        try (CqlSession session = CqlSession.builder().build()) 

            DaoMapper daoMapper = new DaoMapperBuilder(session).build();
            OrderDao orderDao = daoMapper.orderDao(CqlIdentifier.fromCql("killrvideo"));
            CustomerOrders order = orderDao.findById("a");
            System.out.println(order.getCustomerEmail());
        
    

在这种情况下,killrvideo 键空间,因为我正在访问 Astra DB,这就是我目前拥有的键空间。

Result: a@b.c.com

驱动程序版本 4.7.2 在我的 pom.xml 中指定

【讨论】:

我已尝试删除 @Column 注释。没有帮助。此外,主键列名旨在用作id 本身,所以我认为没有必要在那里使用@CqlName 注释。 您能否在问题中包含来自 Cassandra 的 Order 表的 Schema 定义。 嘿@Andrew 我也用架构定义更新了这个问题。 我已经为我的主键 getter/setter 添加了代码 谢谢,我将使用您提供的代码来尝试重现 - CREATE TABLE order_keyspace.order - 您说过键空间称为 order,而不是 order_keyspace,这只是您在粘贴时所做的修改吗? 【参考方案2】:

@Andrew 谢谢,我对@PartitionKey 使用了错误的导入。正确的是你提到的import com.datastax.oss.driver.api.mapper.annotations.PartitionKey;

【讨论】:

以上是关于我已经使用 PartitionKey 注释声明了主键,但仍然得到 Entity Order 没有声明主键的主要内容,如果未能解决你的问题,请参考以下文章

Azure Cosmos SQL API - 如何将自定义对象存储为 @PartitionKey

编辑后的帖子如何从main()运行TestNG测试,我已经编写了主类 - 但是现在呢?

如何在 Azure 表存储中使用 partitionkey 加快查询速度

为什么在依赖注入上使用java进行注释

如何在 libclang c++ 中使用 RecursiveASTVisitor 提取注释并匹配声明?

没有处理器声明任何这些注释:javax.servlet.annotation.MultipartConfig