问题
I'm getting started with Google App Engine, and I'm using Objectify. How do I create a root entity in the data store, but err if it already exists? I didn't find anything built in for this (e.g. DatastoreService.put()
and therefore ofy().save()
will overwrite an existing entity instead of err). The simple technique I am used to is to do this in a transaction:
- Err if already exists
- Save
However, that is not idempotent; it would err in step 1 if the transaction executes twice. Here is the best I've come up with so far, not in a transaction:
- Err if already exists
- Save
- Fetch
- Err if it's not the data we just created
Or, if I don't mind two requests to save the same data both succeeding, I can skip the initial lookup:
- Fetch
- Report success if it's the same data we are about to create
- Err if already exists, but is not the same data we are about to create
- Save
That is doable, but it gets a little bulky to accomplish what I thought would be a very simple operation. Is there a better way?
回答1:
This should guarantee consistent behavior:
final String id = // pick the unique id
final long txnId = // pick a uuid, timestamp, or even just a random number
ofy().transact(new VoidWork() {
public void vrun() {
Thing th = ofy().load().type(thing.class).id(id).now();
if (th != null) {
if (th.getTxnId() == txnId)
return;
else
throw ThingAlreadyExistsException();
}
th = createThing(id, txnId);
ofy().save().entity(th);
}
});
来源:https://stackoverflow.com/questions/22362192/create-or-err-with-objectify