Is there such thing as @Unique to mark field with unique value

1,506 views
Skip to first unread message

Haris

unread,
Mar 11, 2010, 1:18:15 PM3/11/10
to objectify-appengine
Hello,

My understanding is marking field as unique prevent records to have
same value for that particular field. Sort of like @Id. However, we
can only have one id field and this field is part of the Key.

For instance for user records, I would like to have id to be Long and
auto generated. At the same time need a field for username. Which must
be unique.

Question1: Is there such thing as @Unique and enforcement of it? For
instance trying to put object with user name that is already existing
in the datastore will fail.

Question2: At the moment, my work around is to get/filter object with
base on to be registered username and only register if result of the
get/filter is empty. Better way to do this?

Thanks in Advance,
Haris

Jeff Schnitzer

unread,
Mar 11, 2010, 3:58:32 PM3/11/10
to objectify...@googlegroups.com
Sadly, this is one of the things that appengine makes hard. There is
a fair bit of discussion on the appengine mailing lists about the
subject. There is a JDO annotation @Unique but it doesn't do
anything.

Your solution will probably work 99.99% of the time, but it does
introduce a race condition. If you want to guarantee uniqueness 100%
of the time, you need to "lock" the username with a transaction and a
separate entity that has a name @Id.

Start by doing your normal check for username in a filter. If it
passes, here's rough pseudocode:

* Use an entity that looks like this: class UsernameLock { @Id
String username; }
* Start a transaction
* get() the UsernameLock - if one exists, you have a collision
* put() the UsernameLock
* commit() the transaction - if fails, you have a collision
* Create your full entity
* Remove the UsernameLock

Pain in the ass. If you can settle for 99.999% effective, instead of
creating a UsernameLock entity, use the MemcacheService.increment()
method. The code will be a lot simpler. The only race condition
would be if the first username check failed (two creates with the same
username at the same precise moment) and the MemcacheService was
bounced exactly inbetween the two increment() calls.

Personally, I'd use the MemcacheService. After checking the standard filter:

* Call MemcacheService.increment(theusername, 1, 0);
* If the value is nonzero, you have a collision
* Create your User entity
* Don't even need to worry about removing the memcache entry

Jeff

Haris

unread,
Mar 22, 2010, 5:33:27 AM3/22/10
to objectify-appengine
Thanks for the tips.

It will be great though if Objectify have something to handle this
scenario.

With that said... back to the drawing board with your tip in mind.


On Mar 12, 4:58 am, Jeff Schnitzer <j...@infohazard.org> wrote:
> Sadly, this is one of the things that appengine makes hard.  There is
> a fair bit of discussion on the appengine mailing lists about the

> subject.  There is a JDO annotation @Uniquebut it doesn't do

> > My understanding is marking field asuniqueprevent records to have


> > same value for that particular field. Sort of like @Id. However, we
> > can only have one id field and this field is part of the Key.
>
> > For instance for user records, I would like to have id to be Long and
> > auto generated. At the same time need a field for username. Which must
> > beunique.
>

> > Question1: Is there such thing as @Uniqueand enforcement of it? For

Sathyanarayanan Thilakan

unread,
Nov 1, 2013, 1:50:06 AM11/1/13
to objectify...@googlegroups.com, je...@infohazard.org
Hi Jeff,

Thanks for this and heartfelt thanks for making objectify available. It is one of the great libraries i have worked with.

Regarding the use of MemCacheService - should we not check for 1 after increment ?

Pasted from your email....
--------------------------------------------------------------------------------------------------------------------

Personally, I'd use the MemcacheService.  After checking the standard filter:

 * Call MemcacheService.increment(theusername, 1, 0);

 * If the value is nonzero, you have a collision    (should we not check for 1 here ?? )


 * Create your User entity
 * Don't even need to worry about removing the memcache entry

--------------------------------------------------------------------------------------------------------------------


Regards,

Sathya

Reply all
Reply to author
Forward
0 new messages