Ok Bryce...I'm back.  Going to test with your ideas now.  In my case,
I tend to avoid generic column names like "id" in favor of "bookId"
and "chapterId" so I should not have any naming conflicts (at least
rarely).  Also, my FK embedded classes should not have any collections
though I have a feeling they may come up as I get further into it.

I'll just test with Book and owned relation Chapter as you have it
here.  How do we tell JDO whether a relation is "owned" vs "unowned"
by the way?  Because I would like to have a child object of each for
the testing.  Thanks!

On Oct 9, 12:06 pm, bryce cottam <bcot...@gmail.com> wrote:
> FYI, this video was hugely helpful for me, and this information helps
> me decide how to structure my data model to run best on the
> app-engine, it's a Google I/O session on how the app-engine big table
> implementation works:http://www.youtube.com/watch?v=tx5gdoNpcZM
>
>
>
> On Fri, Oct 9, 2009 at 10:46 AM, James H <james.hollier...@gmail.com> wrote:
>
> > Ylmz, thats how I see it too.  Any significant data model will be
> > riddled with FKs and since GAE datastore does not support Joins you
> > have NO choice but to denormalize your data to meet the needs of your
> > app queries.  The Cottam Pattern above allows best management of
> > source to accomplish this denormalization.
>
> > I assume the simple example you are referring to either only stores
> > the Keys in the physical table (which would be insufficient for app
> > queries) or stores the whole record (which would be massive overkill).
>
> > Does that make any sense?
>
> > On Oct 8, 4:46 am, bryce cottam <bcot...@gmail.com> wrote:
> >> yes, I think the point that we are making is that we are trying to
> >> managed "un-owned" relationships  :)
> >> You are describing owned relationships, which I use as well, but in
> >> many cases, I really want un-owned relationships.  For a variety of
> >> reasons really, one of which is that the children I have in my
> >> collection get get rather big, and there is a cap on the number of
> >> writes that can happen on an entity group.  So, in come cases it's
> >> better to model the relationships as foreign keys.
>
> >> The problem comes in when you try to manage your data.  It's a pretty
> >> common suggestion from the app-engine team to denormalize, we're just
> >> trying to come up with a way to denormalize and minimize code
> >> duplication etc.  Denormalizing will let you query better/faster etc.
> >> but can create headaches when trying to update a single field which is
> >> mirrored on several other entities.
>
> >> For instance, you could have an Employee that works for several
> >> departments in a company.  It's the same Employee, so it should be a
> >> single record.  So, in this case you'd have a Company, Division and
> >> Employee.  A Company "owns" it's Divisions and it also "owns" it's
> >> Employees, yet a Division "owns" it's Employees as well.  So, where
> >> does the collection of Employees live?  On the Company, or the
> >> Division?  If it's the Division, then you can't share employees with
> >> other divisions (unless you duplicate the Employee record).  If the
> >> Company owns the Employee, then you have to make some way for the
> >> Division to know who's in it.  You could do this by putting a
> >> collection of Division Key objects on an Employee record, or a
> >> collection of Employee Keys on a Division record.  Yet, this doesn't
> >> allow for simple querying, like "select all employees that work in a
> >> division located in New York and has less than 20 people in it".  Or,
> >> "select all divisions who have an employee named Fred".
>
> >> you can do queries like this if you denormalize the data though  :)
>
> >> On Thu, Oct 8, 2009 at 3:35 AM, ylmz <yilmazhuse...@gmail.com> wrote:
>
> >> > may I suggest different kind of desing
> >> >http://code.google.com/appengine/docs/java/datastore/relationships.html,
> >> > in this document it suggests to use collection types to design one to
> >> > many relation ships.
> >> > and it works pretty well actually. when you use a collection type. app
> >> > engine does not really use the original colection type you used.
> >> > instead
> >> > it uses its own replacement. so if you want to add a new employee to
> >> > the company you just add a new one to the list. it automatically added
> >> > to datastore.
> >> > and if I understand right, when you get a company you dont get all the
> >> > employees inside. you only get a collection type which is actulally
> >> > empty but look like it has employees inside.
> >> > so when you get any element from collection type
> >> > it pulls that record from datastore.
> >> > there is also some collection types that excepts unique values.
> >> > Is there a spesific reason you don't use collections that I didn't
> >> > understand?
>
> >> > On Oct 7, 4:16 am, James H <james.hollier...@gmail.com> wrote:
> >> >> Wow, this is majorly useful...can't wait to try it out!!!  For the
> >> >> life of me I can't figure out why this problem domain has NOT already
> >> >> been exhausted in this Group since denormalization is a requirement
> >> >> with this technology for any significant business application!
>
> >> >> I believe your example should be placed in a section on how to handle
> >> >> Advanced Relations w/Denormalization in this section of the docs:
>
> >> >>http://code.google.com/appengine/docs/java/datastore/relationships.html
>
> >> >> Great work, Bryce!  I'll see if I can break it :)
>
> >> >> As for our other achilles' heel, that being Distributive
> >> >> Transactions...do you think the Open Source team will deliver any time
> >> >> soon?  I worry about contention in that solution since everything is
> >> >> concentrated into 1 table - the DT instruction table...  Meanwhile,
> >> >> I'm thinking about queuing 2nd and N-phase transactions to the Task
> >> >> Queue, yep its a bandaid.
>
> >> >> On Oct 6, 6:29 pm, bryce cottam <bcot...@gmail.com> wrote:
>
> >> >> > oh, I should clarify, the @ReferencedField, is an annotation I wrote,
> >> >> > it's not part of any library or anything:
> >> >> > @Retention(RetentionPolicy.RUNTIME)
> >> >> > @Target({ElementType.FIELD, ElementType.METHOD})
> >> >> > public @interface ReferencedField {
> >> >> >         public String srcField();
>
> >> >> > }
> >> >> > On Tue, Oct 6, 2009 at 5:19 PM, bryce cottam <bcot...@gmail.com> 
> >> >> > wrote:
> >> >> > > Thanks for the update Diana,
> >> >> > > I hadn't thought to look in this forum for a "series"  nice moves  
> >> >> > > :)
>
> >> >> > > I've gotten some pieces of this to work out well so far.  This is an
> >> >> > > overview of what I have (using the Book/Chapter example)
>
> >> >> > > @PersistenceCapable(identityType=IdentityType.APPLICATION,
> >> >> > > detachable="true")
> >> >> > > public class Book {
>
> >> >> > >   �...@primarykey
> >> >> > >   �...@persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
> >> >> > >    private Key id;
>
> >> >> > >   �...@persistent
> >> >> > >    private String title;
> >> >> > >   �...@persistent
> >> >> > >    private String isbn;
>
> >> >> > >    // getters and setters
> >> >> > > }
>
> >> >> > > @PersistenceCapable(detachable="true")
> >> >> > > public class BookFK {
> >> >> > >     �...@persistent
> >> >> > >      private Key id;
> >> >> > >     �...@persistent
> >> >> > >      private String title;
> >> >> > >     �...@persistent
> >> >> > >      private String isbn;
> >> >> > >     // getters and setters
> >> >> > > }
>
> >> >> > > @PersistenceCapable(identityType=IdentityType.APPLICATION,
> >> >> > > detachable="true")
> >> >> > > public class Chapter {
> >> >> > >   �...@primarykey
> >> >> > >   �...@persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
> >> >> > >    private Key id;
>
> >> >> > >   �...@persistent
> >> >> > >    private String title;
> >> >> > >   �...@persistent
> >> >> > >    private int numPages;
>
> >> >> > >   �...@persistent
> >> >> > >   �...@embedded
> >> >> > >    private BookFK book;
>
> >> >> > >    // getters and setters
> >> >> > > }
>
> >> >> > > so, this looks promising, but we still have the problem of name 
> >> >> > > collissions
> >> >> > > (the "title" and "id" fields in this case).
> >> >> > > in order to resolve this, we put a "members" field in our @Embedded
> >> >> > > annotation.  However, I've noticed that JDO seems to like it better 
> >> >> > > if you
> >> >> > > itemize all fields of an embedded class if you itemize any of them:
>
> >> >> > >   �...@persistent
> >> >> > >   �...@embedded(members= {
> >> >> > >         �...@persistent(name="id", colum...@column(name="bookId")),
> >> >> > >         �...@persistent(name="title", 
> >> >> > > colum...@column(name="bookTitle")),
> >> >> > >         �...@persistent(name="isbn")
> >> >> > >     })
> >> >> > >    private BookFK book;
>
> >> >> > > either that, or we need to rename the fields in our BookFK class:
>
> >> >> > > public class BookFK {
> >> >> > >     �...@persistent
> >> >> > >      private Key key;
> >> >> > >     �...@persistent
> >> >> > >      private String bookTitle;
> >> >> > >     �...@persistent
> >> >> > >      private String isbn;
> >> >> > > }
>
> >> >> > > I lean towards the latter when it's simple (like in the "id" vs 
> >> >> > > "key"
> >> >> > > example.  The idea here, is that you're going to be querying on 
> >> >> > > these
> >> >> > > fields, so you probably doing want to make them hard to remember.  
> >> >> > > It'd be
> >> >> > > great if you could always have the fields in the FK class be the 
> >> >> > > same name
> >> >> > > as the fields in the mirrored Entity class.  Then you'd have 
> >> >> > > queryies like
> >> >> > > this:
> >> >> > > select from Chapter where book.id = 1234 and book.title = "The Art 
> >> >> > > of JDO on
> >> >> > > the App-Engine"
> >> >> > > but in our (my) case this get's modified to:
> >> >> > > select from Chapter where book.key = 1234 and book.bookTitle = "The 
> >> >> > > Art of
> >> >> > > JDO on the App-Engine"
>
> >> >> > > I don't so much mind the naming difference, but some people may get 
> >> >> > > annoyed
> >> >> > > by it  :)
>
> >> >> > > So, what we've got above works enough, but the problem is setting 
> >> >> > > fields on
> >> >> > > the BookFK object from the mirrored Book object.  We could have a 
> >> >> > > single
> >> >> > > block of code that does stuff like this:
>
> >> >> > > public static BookFK createFK(Book book) {
> >> >> > >     BookFK fk = new BookFK();
> >> >> > >     fk.setKey(book.getId());
> >> >> > >     fk.setBookTitle(book.getTitle());
> >> >> > >     fk.setIsbn(book.getIsbn());
> >> >> > >    return fk;
> >> >> > > }
>
> >> >> > > and that's fine, it's pretty darn manual, but it is a single place 
> >> >> > > where
> >> >> > > things get updated.
> >> >> > > I found that I could centralize that set/get code by making a simple
> >> >> > > annotation:
> >> >> > > @ReferencedField
>
> >> >> > > so our BookFK turns into this:
>
> ...
>
> read more »- Hide quoted text -
>
> - Show quoted text -
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to