Re: [appengine-java] how to keep fields unique

2011-03-07 Thread emurmur
It turns out the technique I described in my previous post has two issues.

1. Because only one transaction can be running at a time within a process, 
and the entity used as the mutex really cannot be in the same entity group 
as the primary entity, you can get into a situation where the mutex entity 
is orphaned if one transaction succeeds and the following transaction fails. 
 The orphaned mutex entity then prevents anyone for using it's version of 
the unique fields.

2. This solution, when used with JDO or JPA, is very verbose and obfuscates 
the primary intent of the code.  Also, you would never to do this with an 
SQL datastore, so it limits the portability of the code, which is why one 
would choose JDO/JPA in the first place.

Really, we want the uniqueness annotations to be implemented.

There is an issue in the bugbase for this, issue 178.  Folks have been 
talking about this for a long time.  Please star this issue if it is 
important to you.

http://code.google.com/p/googleappengine/issues/detail?id=178


-- 
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 google-appengine-java@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.



Re: [appengine-java] how to keep fields unique

2011-03-04 Thread Ed Murphy
I'm struggling with a bug that is closely related to this thread.  I think 
transactions all by themselves will not work here.  This is because the 
transactions are optimistic.  So, if the transaction looks like this (pseudo 
code)

pm.currentTransaction.begin();
Object preexistingEntity = pm.query(for secondary key);
if(null != preexistingEntity) throw SecondaryKeyException
pm.insert(new Entity(secondary key));
pm.currentTransaction.commit().


The issue (I think) is that because transactions are optimistic, it is still 
possible for a race condition.  Two separate processes can create a 
transaction and attempt to read the preexistingEntity.  If they are very 
close in time (like my case, 32 milliseconds), then they will both return 
null, since the entity does not yet exist.  So, neither process will throw 
the SecondaryKeyException.  The will both go on and create new entitities 
and insert them.  Each of these entities will have different primary keys 
because the database creates these, but the entity's secondary key (an email 
address in this case) is not enforced by the database, so there is no error 
on either commit.  Thus, I end up with two entities with a duplicate value 
for a field that I want to be unique.  

I my case, this happened when the user double-clicked an activation link; 
 The server received two requests within 50 milliseconds of each other and 
both transactions completed without error.  

I want to use a human readable, unique field for my users names.  I need the 
database generated unique id to create relationships with other entities 
that survive even if the human readable field is changed.  For instance, if 
a user changes their email address, I don't want to have to go around to all 
the possible related entities and fixup references to it.  So, I use the 
primary Key for this.  But I still want the email address to be unique in 
the database.

Anyone from Google know how to make this happen?  HELP


-- 
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 google-appengine-java@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.



Re: [appengine-java] how to keep fields unique

2011-03-04 Thread Ed Murphy
OK, here is something that looks promising; 

http://squeeville.com/2009/01/30/add-a-unique-constraint-to-google-app-engine/

This shows a solution in python, but the concept is applicable to Java. 
 Basically, for the unique field, you create another database entity and 
derive a primary Key based on the unique field.  Since the database ensures 
uniqueness of a primary key, this means that we can atomically create and 
check the existence of this entity.   So my pseudocode might look like;

pm.currentTransaction.begin();
Object preexistingKey = pm.insert(new SecondaryKeyEntity(secondary key));
pm.currentTransaction.commit();

//
// if we get here, then the previous transaction completed and
// no other process will be able to get to this section of the code
// using the same secondary key
//
pm.currentTransaction.begin();
pm.insert(new Entity(secondary key));
pm.currentTransaction.commit().

Of course, you need to do something similar when you change the secondary 
key (for instance, if someone wants to update their email address).  Again, 
just attempt to create an 'SecondaryKeyEntity' with the new email address. 
 If that successes, then you can change the email address in the primary 
entity.  Remember to delete the old SecondaryKeyEntity after!!

I'll work on this over the weekend and post some code if I figure it out.  

In the mean time, if anyone has already done this, please let us know. 
 Thanks.

-- 
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 google-appengine-java@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.



Re: [appengine-java] how to keep fields unique

2010-02-16 Thread John Patterson
You could use transactions if all Servers are in the same entity  
group.  In a transaction you can query for existing A specifying the  
ancestor in the query.  When you find no other Server with the key you  
can store it - also with the same ancestor - then commit the  
transaction.  If another request saved the same key in between an  
exception would be thrown so you could try another key.



On 17 Feb 2010, at 11:58, smile laugh wrote:


hello everyone

I have several fields which must be unique because of business
logic.how can app engine make the unique key for the several fields?

For example, in a Server A ,I query a value and find there is no
existing value ,  so I insert value into Server A successfully.
But almost the same time , another one can do the same thing(insert
the same record) successfully in Server B.
Because at this time , Server A and Server B are not consistent,
the prior inserts will all  be successful.

how can I avoid to insert the same records?

--
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 google-appengine-java@googlegroups.com 
.
To unsubscribe from this group, send email to google-appengine-java+unsubscr...@googlegroups.com 
.
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 google-appengine-j...@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.