If you have an account that looks like this:

class Account {
    @Id Long id;
    String email;
}

Two people can create Accounts at the same time with the same email
address.  Or someone could change their email address at the same time
someone creates an account.  Or two people could change their email to
the same address at the same time.  You get the picture.

You can't use transactions because the Account objects are in separate
entity groups.  Nothing prevents the same email address from being
attached to two accounts, so you might get a collision.  Since login
is done by email address, one of these users is screwed.

Jeff

On Mon, Feb 22, 2010 at 10:55 PM, John Patterson <[email protected]> wrote:
> I don't see what extra protection storing an email as a separate entity buys
> you.  If you store the same email address twice you do not get an exception
> thrown like in an RDBMS... it just silently overwrites the existing one.  In
> either case, storing the email as a key or as a field, you would need to do
> a query (or get) in a transaction to be sure you were not going to overwrite
> an existing record with the same email.
>
> On 23 Feb 2010, at 13:37, Jeff Schnitzer wrote:
>
>> I don't think we're disagreeing - user-defined keys are the only way
>> to enforce uniqueness.  I was just trying to point out that
>> user-defined longs work just as well for enforcing uniqueness as
>> user-defined Strings if your natural key is numeric.  There's no
>> reason to convert it to a String.
>>
>> I don't personally think there's anything wrong with carefully chosen
>> natural keys.  Domain name in your example is a great natural key.
>>
>> Accounts with an email address is a little weirder.  You want two
>> things:  Accounts should be able to change their email addresses (so
>> using the email as the Account key is a bad idea) but you also want to
>> enforce uniqueness of the email address field (users use it to log
>> in).  So the appropriate model for this in appengine is probably to
>> have Account and Email as separate entities, Account with a generated
>> id and Email with a tautological natural key.
>>
>> ...which provides one more illustration of why the JDO claim of
>> "transparent persistence" across multiple datastores is bogus.  You'd
>> never do this in an RDBMS.
>>
>> Jeff
>>
>> On Mon, Feb 22, 2010 at 8:09 PM, Max Ross (Google)
>> <[email protected]> wrote:
>>>
>>> Jeff,
>>>
>>> I agree with the majority of your design philosophy and the advice you're
>>> dispensing, but I still disagree with you on one pretty fundamental
>>> point.
>>> If I'm understanding your argument correctly, you're saying that best
>>> practices for primary key management don't involve user-defined strings,
>>> therefore user-defined strings aren't a necessary feature, but I think
>>> this
>>> ignores a pretty basic usage of uniqueness constraints.  Let's say you're
>>> a
>>> domain registrar, you're building your registration workflow on App
>>> Engine,
>>> and you need to guarantee that a domain name can only be claimed once.
>>>  If
>>> you use a numeric id mapped to the domain name you run the risk of
>>> letting
>>> two users reserve the same domain, and if you're a domain registrar
>>> that's
>>> really really bad.  There's no natural key we can bring in here.  Whether
>>> we
>>> as application developers run into them frequently or not, there exists a
>>> class of problems where a user-defined string pk is a necessary part of
>>> the
>>> solution.
>>>
>>> Regards,
>>> Max
>>>
>>> On Mon, Feb 22, 2010 at 1:52 PM, Jeff Schnitzer <[email protected]>
>>> wrote:
>>>>
>>>> On Mon, Feb 22, 2010 at 1:19 PM, Max Ross (Google)
>>>> <[email protected]> wrote:
>>>>>
>>>>> user-defined long-id keys are not quite as easily used.  You either
>>>>> need
>>>>> to
>>>>> commit to not letting the datastore generate ids for that kind or you
>>>>> need
>>>>> to reserve a batch of ids using the DatastoreService.allocateIds
>>>>> method.
>>>>> Otherwise you run the risk of a silent collision.  There is no such
>>>>> risk
>>>>> with user-defined string keys.
>>>>
>>>> Right, but if the user has a natural key (long, String, whatever) they
>>>> won't be using the generator anyways.  There are plenty of natural
>>>> long keys in the world... facebook userid being a popular one.
>>>>
>>>> FWIW, Objectify makes the distinction between ids of type Long, which
>>>> can be null and thus autogenerated, and long (the primitive) which
>>>> cannot be autogenerated.  I really hadn't intended to plug Objectify
>>>> here, really!
>>>>
>>>>> Valid point about renaming, but going back to the example I provided,
>>>>> the
>>>>> datastore does not distinguish between inserts and updates.  The only
>>>>> way
>>>>> you can guarantee that an entity was inserted, and therefore the only
>>>>> way
>>>>> you can guarantee the uniqueness of the name, is to use a user-defined
>>>>> key.
>>>>> If you're mapping id to name it will be possible to create two entities
>>>>> with
>>>>> the same name.  It's of course up to you to decide how important this
>>>>> is
>>>>> to
>>>>> defend against, but without the ability to provide your own id you
>>>>> wouldn't
>>>>> get to make this choice, and without the ability to provide your own
>>>>> string
>>>>> id you wouldn't be able to add some application-specific meaning to
>>>>> this
>>>>> choice.
>>>>
>>>> I totally agree with you WRT user-defined vs generated values, I just
>>>> don't see anything wrong with using the long id as a user-defined
>>>> value.  Just make sure you never ask for a generated one.  Seems
>>>> pretty straightforward.
>>>>
>>>> Jeff
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups
>>>> "Google App Engine for Java" group.
>>>> To post to this group, send email to
>>>> [email protected].
>>>> To unsubscribe from this group, send email to
>>>> [email protected].
>>>> For more options, visit this group at
>>>> http://groups.google.com/group/google-appengine-java?hl=en.
>>>>
>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "Google App Engine for Java" group.
>>> To post to this group, send email to
>>> [email protected].
>>> To unsubscribe from this group, send email to
>>> [email protected].
>>> For more options, visit this group at
>>> http://groups.google.com/group/google-appengine-java?hl=en.
>>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Google App Engine for Java" group.
>> To post to this group, send email to
>> [email protected].
>> To unsubscribe from this group, send email to
>> [email protected].
>> For more options, visit this group at
>> http://groups.google.com/group/google-appengine-java?hl=en.
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Google App Engine for Java" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/google-appengine-java?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.

Reply via email to