首页 文章

如何将HashMap(作为对象属性)保存到数据存储区

提问于
浏览
3

我正在使用GAE(Google App Engine)数据存储来存储人员 .

每个人都有一个名字,一个唯一的标记,他们收到的消息列表(字符串)和他们完成的测试列表(字符串) . 这些都是supported types .

但是,我还想存储一个包含String键和String值的HashMap,以及有关它们已完成的测试的信息 .

我正在尝试保存的示例Map(请注意,这是示例数据,而不是实际数据)

[
    <'test_easy_1', 'completed in 3 minutes'>
    <'test_easy_2', 'completed in 5 minutes'>
    <'test_hard_1', 'completed in 15 minutes'>
    <'test_hard_2', 'completed in 3 minutes.. Did you cheat?'>
]

我想拯救这样的人

@Override
public boolean savePerson(Person p) {
    if (p.getEntity() == null) {
        return false;
    }

    p.getEntity().setProperty("name", p.getName());
    p.getEntity().setProperty("token", p.getToken());
    p.getEntity().setProperty("messages", p.getMessages());
    p.getEntity().setProperty("completedTests", p.getCompletedTests());
    p.getEntity().setProperty("testInformation", p.getTestInformation()); // does not work
    DatastoreServiceFactory.getDatastoreService().put(p.getEntity());

    return true;
}

现在我的问题:

如何将HashMaps作为对象属性保存到数据存储区?

我希望以一种我不想知道如何这样做的方式来执行此操作 . 谷歌搜索这并没有导致一种明确和明显的方式来处理这种情况 .

3 回答

  • 5

    您可以使用Twist轻松实现此目的:

    Map toSave = new LinkedHashMap();
    toSave.put("name", p.getName());
    toSave.put("token", p.getToken());
    toSave.put("messages", p.getMessages());
    toSave.put("completedTests", p.getCompletedTests());
    toSave.put("testInformation", p.getTestInformation()); 
    
    store().put(toSave);
    

    这就是将Map保存到数据存储区的方法 .

    您也可以采用这样的POJO方法(使用Twist):

    @Entity
    class TestInfo{
       @Id
       Long id;
       @Flat
       Map fields; 
    }
    

    然后做:

    TestInfo info = new TestInfo();
    info.setFields(map); 
    
    store().put(info);
    

    请注意,您可以将 @Flat@Embedded 用于Map字段,如果使用Flat,则表示twist将存储不在EmbeddedEntity中的字段,它将成为数据存储区中Entity属性的一部分 . 否则,使用@Embedded将其存储在EmbeddedEntity中 . 这取决于您的需求,但这两个选项都可用 .

  • -1

    虽然其他答案可能是正确的,但我主要是在寻找一种方法来实现这一点,而无需使用外部库 .

    我已经对前面提到的EmbeddedEntity进行了一些研究,发现这确实是我想要的 .

    我正在编写并接受这个答案,因为它为我的问题提供了一个精确的解决方案,而不仅仅是解决问题的指导方针 . 我希望通过这种方式引导未来遇到类似问题的人们 .

    现在保存此人看起来像这样:

    @Override
    public boolean savePerson(Person p) {
        if (p.getEntity() == null) {
            return false;
        }
    
        p.getEntity().setProperty("name", p.getName());
        p.getEntity().setProperty("token", p.getToken());
        p.getEntity().setProperty("messages", p.getMessages());
        p.getEntity().setProperty("completedTests", p.getCompletedTests());
    
        EmbeddedEntity ee = new EmbeddedEntity();
        Map<String, String> testInformation = p.getTestInformation();
    
        for (String key : testInformation.keySet()) { // TODO: maybe there is a more efficient way of solving this
            ee.setProperty(key, testInformation.get(key));
        }
    
        p.getEntity().setProperty("testInformation", ee);
        DatastoreServiceFactory.getDatastoreService().put(p.getEntity());
    
        return true;
    }
    

    现在加载此人看起来像这样:

    Person p = new Person(id);
    p.setName((String) e.getProperty("name"));
    p.setToken((String) e.getProperty("token"));
    p.setMessages((List<String>) e.getProperty("messages"));
    p.setCompletedTests((List<String>) e.getProperty("completedTests"));
    
    Map<String, String> ti = new HashMap<>();
    EmbeddedEntity ee = (EmbeddedEntity) e.getProperty("testInformation");
    if (ee != null) {
        for (String key : ee.getProperties().keySet()) {
            ti.put(key, (String) ee.getProperty(key));
        }
        p.setTestInformation(ti);
    }
    p.setEntity(e);
    
  • 1

    您可以将其另存为嵌入式实体 .

    我建议使用Objectify来简化存储并减少样板:https://code.google.com/p/objectify-appengine/wiki/Entities#Maps

    您可以通过在Map字段上注释@Index来创建索引 .

相关问题