java—如何将哈希Map(作为对象属性)保存到数据存储

tyu7yeag  于 2021-07-03  发布在  Java
关注(0)|答案(3)|浏览(380)

我正在使用gae(googleappengine)数据存储来存储人。
每个人都有一个名字,一个唯一的标记,一个他们收到的消息列表(字符串)和一个他们完成的测试列表(字符串)。这些都是受支持的类型。
但是,我还想存储一个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作为对象属性保存到数据存储?
我希望以一种不必为hashmap创建整个类和新的数据存储索引的方式来执行此操作。然而,如果这是唯一的办法,我想知道如何这样做。在谷歌上搜索这一点,并没有找到一个清晰而明显的方法来处理这种情况。

xpszyzbs

xpszyzbs1#

您可以通过扭曲轻松实现这一点:

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将存储不在嵌入实体中的字段,它将是数据存储中实体属性的一部分。否则,使用@embedded将其存储在embeddedentity中。这取决于你需要什么,但这两个选项是可用的。

brgchamk

brgchamk2#

可以将其另存为嵌入实体。
我建议使用objectify,它可以简化存储并减少样板文件:https://code.google.com/p/objectify-appengine/wiki/entities#maps
只需在map字段中注解@index,就可以创建索引。

3ks5zfa0

3ks5zfa03#

尽管其他答案可能是正确的,但我主要是在寻找一种不使用外部库来实现这一点的方法。
我对前面提到的嵌入实体做了一些研究,发现这确实是我想要的。
我写并接受这个答案,因为它给了我的问题一个确切的解决方案,而不仅仅是解决它的指导方针。我希望通过这种方式来指导将来遇到类似问题的人。
救人现在看起来是这样的:

@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);

相关问题