RobinBattle
RobinBattle

Reputation: 228

Google App Engine(Java) database auto-generated ID

In Google App Engine Java,

When I do:

ProjectData pd = new ProjectData();
pd.id = null;  // let Objectify auto-generate the project id
pd.dateCreated = date;
datastore.put(pd); // put the project in the db so that it gets assigned an id

The database will automatically assign an unique ID to each pd, when run "datastore.put(pd)". Yet, if I add parent key field:

ProjectData pd_new= new ProjectData();
pd_new.id = null;  // let Objectify auto-generate the project id
pd_new.parentKey= new Key<OtherData>(OtherData.class, anotherId);
pd_new.dateCreated = date;
datastore.put(pd_new);

Even Though the id will still be auto-generated, it is not unique any more. The ids are always the same. For example, I have 7 ProjectData in database, their Ids are all "5629499534213120"

My data structure is

public class ProjectData {
  @Id Long id;
  @Parent Key<OtherData> parentKey;
  long dataCreated; 
}  

Did I do something wrong here, this bugs me for days.


BTW, I can fix it by manually assigning each of them

pd_new.id = System.currentTimeMillis();

But I don't think this is an appropriate way to do it.

Upvotes: 2

Views: 1457

Answers (2)

adevine
adevine

Reputation: 1102

To add more detail to Andrei's answer:

In AppEngine, there are 5 parts that make up a Key, and it's only these 5 parts TOGETHER that guarantee uniqueness across all Keys in AppEngine:

  1. The ID of your app.
  2. The namespace, which is used in multi-tenancy applications.
  3. The Entity type name.
  4. The full Ancestor path.
  5. The ID of this entity.

Thus, it's possible for entities of different types to have the same ID, and furthermore, it's possible to have entities of the SAME type, but with different ancestor paths, to have the same ID. One corollary of this is that if you have an object, but change its parent, it creates a whole NEW object - it doesn't update the existing one. Thus, you should never model relationships as parent-child in AppEngine if it's possible for an entity to be re-parented.

Thus, if you're using Objectify, one thing I recommend is to only ever expose the KEY (possibly the web-safe string version), and NOT the ID, publicly from your object. The other option you have is to use a String ID, but populate it with a UUID.randomUUID before saving.

Upvotes: 3

Andrei Volgin
Andrei Volgin

Reputation: 41099

This is the correct behavior. Why does it bother you?

In order to get() an entity from the Datastore, you need to create its key. To do so, you need a parent key and an child entity ID. This makes this key always unique (parent entities always have different IDs), even if child entities of other parent entities have the same ID.

Upvotes: 1

Related Questions