【问题标题】:key of child datastore entity returns as null子数据存储实体的键返回为 null
【发布时间】:2013-04-30 18:17:50
【问题描述】:

我有一个典型的 Person-Address 实体关系。在查询数据存储中的 Person 之后,我会查询 Person 以获取地址键。密钥(即addrKey,见下文)始终返回为空。但是我查看数据存储区,我看到了 Person 和 Address 实体,以及它们的键。很明显,Key addrKey = (Key) person.getProperty("address") 这条线并没有做我认为应该做的事情。任何想法如何解决这个问题?

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    Map<Key, Entity> entities = datastore.get(keys);

    List<Person> result = new ArrayList<Person>();
    Iterator<Entry<Key, Entity>> it = entities.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry<Key, Entity> ent = it.next();

        final Entity person = ent.getValue();
        Key key = person.getKey();
        name = (Long) person.getProperty("name");
        Address address = getAddress(datastore, person);

...
    }


private Address getAddress(DatastoreService datastore, Entity person) {
    Key addrKey = (Key) person.getProperty("address");
    try {
        Entity d = datastore.get(addrKey);
        String street = (String) d.getProperty("street");
…
}

【问题讨论】:

    标签: google-app-engine google-cloud-datastore


    【解决方案1】:

    我的猜测是您同时保留了地址和人员。但是,默认情况下,地址在持久化之前具有不完整的键(假设您依赖于键的自动 id 生成)。因此,您亲自存储了不完整的密钥。并且使用不完整的键获取将不起作用。

    我写了一个快速测试用例:

    import com.google.appengine.api.datastore.DatastoreService;
    import com.google.appengine.api.datastore.DatastoreServiceFactory;
    import com.google.appengine.api.datastore.Entity;
    import com.google.appengine.api.datastore.Key;
    
    public class TempTest extends PersistenceTestHelper {
    
      @Test
      public void testStackOverflow() throws Exception {
    
        Entity address = new Entity("address", 1);
        address.setProperty("street", "my street");
    
        Entity person = new Entity("person", 1);
        person.setProperty("addressKey", address.getKey());
        System.out.println(person);
    
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
        datastore.put(person);
        datastore.put(address);
    
        Entity personFromDatastore = datastore.get(person.getKey());
        Key addressKey = (Key) personFromDatastore.getProperty("addressKey");
        Entity addressFromDatastore = datastore.get(addressKey);
        System.out.println("fetched street: " + addressFromDatastore.getProperty("street"));
    
        address = new Entity("address");
        System.out.println("Address with incomplete key: " + address.getKey());
        try {
          addressFromDatastore = datastore.get(address.getKey());
        } catch (IllegalArgumentException e) {
          System.out.println(e);
        }
      }
    
    }
    

    这是输出:

    <Entity [person(1)]:
        addressKey = address(1)
    >
    fetched street: my street
    Address with incomplete key: address(no-id-yet)
    java.lang.IllegalArgumentException: address(no-id-yet) is incomplete.
    

    如果我错了,很高兴能理解为什么你的示例中有一个 try catch。在 pre-put 时间和 pos-get 时间打印出 Person 实体和 Address 实体也很好。

    【讨论】:

    • 我也有这个没有身份的问题。但是我设法通过首先将人员放入数据库来解决它,然后创建地址实体并使用最近创建的地址实体中的密钥更新数据库中的人员实体属性。但是,如果我需要在交易中同时拥有个人和地址实体怎么办?如果没有同时添加地址实体,则无法添加(提交)人员实体?你是怎么做的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多