代码之家  ›  专栏  ›  技术社区  ›  aCarella

尝试使用DynamoDBMapper时出现异常:哈希键没有映射

  •  1
  • aCarella  · 技术社区  · 7 年前

    我有一个DynamoDB表,它有主键(id:integer)和辅键(dateTo:String)。我创建了一个利用DynamoDBMapper的类:

    @DynamoDBTable(tableName="MyItems"
    public class MyItemsMapper {
        private int id;
        private String dateTo;
        private String name;
    
        @DynamoDBHashKey(attributeName="id")
        public void setId(int id) { this.id = id; }
        public int getId() { return id; }
    
        @DynamoDBAttribute(attributeName="dateTo")
        public void setDateTo(String dateTo) { this.dateTo = dateTo; }
        public String getDateTo() { return dateTo; }
    
        @DynamoDBAttribute(attributeName="name")
        public void setName(String name { this.name = name; }
        public String getName() { return name; }
    
        public boolean saveItem(MyItemsMapper item) {
          try {
            DynamoDBMapper mapper = new DynamoDBMapper(client); //<-- This connects to the DB. This works fine.
            item.setId(generateUniqueNumber()); //<-- This generates a unique integer. Also seems to work fine.
            mapper.save(item);
            logger.info("Successfully saved item. See info below.");
            logger.info(item.toString());
            return true;
          } catch (Exception e) {
            logger.error("Exception while trying to save item: " + e.getMessage());
            e.printStackTrace();
            return false;
          }
        }
    }
    

    然后我有一个使用上面bean的manager类,如下所示:

    public class MyManager {
        public boolean recordItem(
                int id,
                String dateTo,
                String name,
        ) {
            MyItemsMapper myItemsMapper = new MyItemsMapper();
            myItemsMapper.setId(id);
            myItemsMapper.setDateTo(dateTo);
            myItemsMapper.setName(name);
            myItemsMapper.saveItem(myItemsMapper);
        }
    }
    

    我正在JUnit测试中运行manager类:

    public class MyManagerTest {
        @Test
        public void saveNewItemTest() {
            MyManager myManager = new MyManager();
            myManager.recordItem(1234567, "2018-01-01", "Anthony");
        }
    }
    

    当我使用 saveItem 方法通过我的管理器运行JUnit测试,我得到以下错误:

    com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException: MyItemsMapper; no mapping for HASH key
    

    我不太确定它与什么有关,因为我的表肯定有一个主键,而我的辅助键也总是有一个值。

    我怎样才能让它工作?

    更多信息:

    值得注意的是,我可以通过 Item object . 如果我执行以下操作,我的数据将记录到数据库中:

    DynamoDB dynamoDB = new DynamoDBClient().connectToDynamoDB(); //<-- 
    Connection. Works fine.
    Table table = dynamoDB.getTable("MyItems");
    item.withPrimaryKey("id", 1234567);
    item.withString("dateTo", "2018-01-01");
    item.withString("name", "Anthony");
    PutItemOutcome outcome = table.putItem(item);
    

    然而,我正在尝试使用DynamoDBMapper,因为我了解到它是一种更有组织、更好的数据访问方式。

    1 回复  |  直到 7 年前
        1
  •  1
  •   F_SO_K    7 年前

    我不确定这是否是导致问题的原因,但您正在创建myItemsMapper对象,然后将对此对象的引用传递给自身。

    我建议删除saveItem方法。MyItemsMapper类应该是一个普通的旧java对象。那就让我的经理这样

    public class MyManager {
        public boolean recordItem(
                int id,
                String dateTo,
                String name,
        ) {
            MyItemsMapper myItemsMapper = new MyItemsMapper();
            myItemsMapper.setId(id);
            myItemsMapper.setDateTo(dateTo);
            myItemsMapper.setName(name);
            DynamoDBMapper mapper = new DynamoDBMapper(client); 
            mapper.save(myItemsMapper);
        }
    }
    

    如果您特别想保留saveItem方法,请如下所示

    public boolean saveItem() {
      try {
        DynamoDBMapper mapper = new DynamoDBMapper(client);
        mapper.save(this);
        logger.info("Successfully saved item. See info below.");
        logger.info(this.toString());
        return true;
      } catch (Exception e) {
        logger.error("Exception while trying to save item: " + e.getMessage());
        e.printStackTrace();
        return false;
      }
    }
    

    然后在MyManager中

        MyItemsMapper myItemsMapper = new MyItemsMapper();
        myItemsMapper.setId(id);
        myItemsMapper.setDateTo(dateTo);
        myItemsMapper.setName(name);
        myItemsMapper.saveItem();