2
votes

I have a typical Person-Address entity relationship. After I query the datastore for Person, I then query Person for the key of address. The key (i.e. addrKey, see below) always returns as null. But I look in the datastore, I see both Person and Address entities, with their keys. So clearly the line Key addrKey = (Key) person.getProperty("address") is not doing what I think it should be doing. Any ideas how to fix this?

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");
…
}
1

1 Answers

0
votes

My guess is that you persisted address and person at the same time. However, address by default has an incomplete key until it is persisted (assuming you're relying on auto id generation for keys). Therefore, you stored an incomplete key in person. And fetches using incomplete keys will not work.

I wrote up a quick test case:

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

}

And this is the output:

<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.

If I'm wrong, it would be nice to understand why you have a try catch in your example. And also a printout of the Person entity and Address entity at pre-put time and pos-get time would be nice.