WWDC2003 Session 616
Transcript
Kind: captions
Language: en
my name is Ben Trumbull and i'm a senior
engineer with the development
technologies group here at Apple and
Steve miner is going to be assisting us
with some demos and he's one of our
fellow engineer so this year we're going
to try to do something a little bit
different we're going to try to provide
a brief overview of a variety of topics
some topics that are challenged you in
the past so last year we talked about
some things with validation and key
value coding and we're going to try to
just skip over all that stuff so
basically the session isn't about
anything you can find the documentation
for the most part and the documentation
of particular relevance to this
particular topic eof is going to be the
5.2 Delta documentation and I believe
they call it what's new in 5.2 on the
website and the eof developer guide so
kind of a show of hands of who's
actually read the republish eof
developer guide it was redone rewritten
this februari so Brent shank and all the
people in tech pubs did a fantastic job
rewriting this includes Mostyn material
includes most material from last year's
advanced session so we're going to have
to keep pushing further so when I said a
brief overview we've got about five
slides for all multi-threaded
programming this is going to go pretty
quick it's really more about identifying
obstacles and getting you to ask the
right questions and then you can go back
to documentation or community resource
one of the mailing list to get more
information so first on our agenda is
memory management and us we're going to
assume you know something about how
garbage collection works in Java and the
difference between strong and weak
references some interesting point is you
can create your own subclass for weak
reference and UF does this it's a handy
little trick eof also uses a mechanism
called false and false our enterprise
objects that have not been initialized
yet so they're lazy initialization at
work and they provide assistance in
memory management as the boundary for
the active object graph everything
beyond the fault is not fetch from the
database deferred faults are a special
kind of fault using too many
relationships and there
definitely more memory efficient because
until you touch them the first time they
are empty if they don't have anything
they're just a little fault and then
they grow to expand to include one fault
for each object in the queue many
relationship and finally share it in
context another mechanism you can use to
reduce your memory and it's probably
best to think of these as read-only
object stores and we'll talk more about
that later so a lot of changes went into
52 that are under the hood so hopefully
not too much epi impact on you but a lot
of things did happen and the first is a
lot of complaints about editing context
using strong references to their
Enterprise objects this has been changed
Enterprise objects are now held with
weak references so the garbage collector
can come along and just start pruning
the object graph of things that you're
no longer accessing directly only
modified objects or things that are
inserted deleted or updated our skill
rate retained an enterprise objects have
a reference back to their editing
context now and it will hold the editing
context in memory until it's done using
it so you have to be careful not to have
any Enterprise objects floating around
but this is better than previous years
where if the editing context guard was
collected first the enterprise optics is
no longer very useful consequence of
these changes is that the registered
objects method is not really useful
since these objects who's going to be
pruned just sort of randomly by the
garbage collection thread you can't
count on anything still being there I
know people in the past have bound their
boat components to this method to just
grab everything in the editing context
you really are never going to know what
you get if you want to lock in object
wrap into memory you can use set retains
registered objects on it editing context
and you can only do this when the
edingtons doesn't have any objects in it
but that will change the way it works
and it will hold everything with strong
reference and share that in context
always use strong references otherwise
they wouldn't be very useful so a bit
about faulting something many people
don't realize is that the size of your
fault is the same as the size of the
enterprise object that represents
referred faults as I mentioned earlier
are significantly more memory efficient
than the too many relationships they
represent and enterprise objects can
extend your generic records to
transparently in
harris the deferred faulting future if
you subclass directly from you a custom
object you're not going to get deferred
faulting by default and away from
scratch can't wait for insertion so this
is on the faulting page because faults
are constructed the same way Enterprise
objects are and this is due to strong
typing in Java so we've got to create a
new enterprise object when we're
creating a Fault in vice versa it means
that if you have a constructor on your
enterprise object you're going to start
doing things while we're faulting this
is bad it defeats the purpose of lazy
initialization in addition when the
fault gets fired that's when iOS thinks
that it's going to finish the
initialization so it's going to
overwrite stuff and it might just ignore
things completely and typically at the
time that the constructor in an
enterprise object is invoked by the vm
that object is not inserted into the
editing context yet so that means any
changes you make in there aren't going
to get noticed by the editing contact
and that breaks pretty much everything
so you really really have to use away
from fetching away from insertion and so
some basic memory optimizations blobs
and clubs should be factored into their
own tables and access to a relationship
and then the relationship can be faulted
and keep the in-memory object graph is
small as possible some other things that
some people do you know you don't want
to over optimize too early but having
too many relationships not be a class
property can be very helpful so there's
a lot of overhead and managing
relationship or there can be
particularly for very large too many so
if you don't need both sides of the
relationship between two related AOS you
can have it be a uni-directional
relationship instead of bi-directional
and you can put rarely use attributes
across the relationship the same way you
would with a blob or a clob and you can
replace it too many entirely with a set
and one of the nice things about this is
it can be vended as a java method and
two key value coding and the rest of us
it looks exactly like in a property on
your enterprise object but instead I can
be a hand coded fetch it's doing
something special so shared editing
context I like this pinch of this is
probably one of the most badly named
classes and us and it's not that it's
too long or too short and it's not that
technically it's not a shared
in context it is unfortunately the best
behavior is a read-only object store
it's not really an editing context and
if you try to use it just like an
editing context you're going to run into
some problems and if you try to use it
as a shared area of read/write use
they're also going to run it from its
best is using read-only years in here
and then you can modify other ears
related to them in your regular editing
contest the main advantage of this
despite those complications is you get
to reuse the memory for the entire
enterprise object instead of just the
row level snapshot which is what
normally happens between editing context
and it's very important not to have
outgoing relationship so if you have a
relationship coming from a shared year
going into any oh and a regular editing
contact us will be very unhappy with you
and share that in context and regulating
context should all use the same objects
or coordinator so much more than that
insect so you've got a million he is the
most important advice I can give you to
defy the operations in two batches most
users are not going to interact with a
million years at the same time anyway
and if they're browsing through a result
set they're probably going to browse the
first few sets before they get bored so
that's the best advice you can use raw
rose and you can fetch bad just the
primary keys or some other subset of the
year so you don't have to bring the full
yo into memory and project wonder
already has some of the stuff done for
you so you can use their such
specifications batch iterator to do
batching and it basically actually
incorporates all these ideas and they
just tons of stuff in project wonder so
more advanced techniques that you can
use is you can intercept the roads as
they're being fetched at the adapter
level and you can use a custom jdbc
channel subclass it can override set row
and as you're going through you can use
a row and then throw it away and in this
way us will not keep all of the result
set in memory and dave newman who is one
of the speakers for the previous session
actually has done this and got an order
of magnitude improvement in peak memory
use for one of his reporting tools so it
works
okay so next on our agenda is data
freshness the u.s. is a big cash and
it's cashing the rows from your database
and editing context build an object
graphs mapping on top of this cache the
data freshness is about when and how to
refresh his cache lines and in us we
call them snapshots reef all thing is
about taking an enterprise object and
turn it back into an uninitialized fault
this is an important mechanism for
saving memory as it prunes entire
branches out of the object graph
invalidating is a little bit like
resulting and a lot of people get the
two mixed up the main difference is
unlike gently sharing the object graph
you're using a chainsaw such time stamps
measure staleness for those snapshots
and the EO database object is to cache
object that you can work with and you
can get at it through the EO database
context through your objects for
coordinated so just to really kind of
home in on why resulting is much better
than in validation resulting effect only
one editing context there are no
notifications no effect on other editing
contexts or other user sessions the
existing snapshot gets reused if it's
fresh enough and there's no trip back to
the database so it's much more gentle on
your performance now if the snapshots to
scale then it will have to go back to
the database research that row and get
you something that's fresh enough for
your configuration and that will post a
notification invalidating affects the
whole stack infects everyone using that
object store coordinator editing
concepts can lose changes for that
object because you've just smashed it
and the snapshot will be discarded and
the next time any editing context
touches that object which is now a fault
around trip to the database will occur
now sometimes you do have to invalidate
so some things keep in mind you really
don't want to end up in a position where
you basically invalidate a lot of
objects there now salt and you're going
through and you're telling us one at a
time is firing us all to go back to the
database because that's going to cost
thousands of round trip to the database
that's something you want to avoid
basketball thing in your relationship
can help them merely ate some of this
but really a manual fetch with an object
of such sophistication is probably the
best way to go you invalidate a set of
fix that you know about and then you go
and you do a fetch for the working set
that you expect to be using next in this
way you're going to minimize folding and
prefetching keypads are extremely useful
for doing this and grabbing a whole lot
of data at one so refresh object I
believe this is introduced in 5.1 it's a
smarter reef alt object it merges
changes back into the enterprise object
in that editing context so it'll pick up
any changes that occurred to the
snapshot it skips over inserts which
can't be resulted and it reuses the
existing Road snapshot unless it's too
stale so the most important thing to
understand about sketch timestamps is
they just don't work the way you want
them to such timestamp lag is relative
and it defaults to one hour and you're
not really going to have a whole lot of
interaction with this but what this
means is when a new editing conduct its
created its fetch timestamp gets set to
one hour ago and that's all the data it
considers fresh enough so those such x
clamps are always absolute like June
twenty fifth for 15 p.m. if we created
an edited context right about now and no
matter how long that in context stays
around say three days in your
application it's going to consider all
the data since jun 25th for 15 p.m. to
be fresh enough most people don't want
that and right now you're going to have
to work around it by periodically
resetting the fetch time can a good
places do that is in session awake
that's a great time a callback you know
the users now interacting with that
default session editing context again
you can also refresh rose with a fetch
specification and setting the set
refreshers refreshed object flag and did
i mention prefetching is a great way to
get lots of data at once so another
advanced technique and i haven't seen
very many people do this the EO database
is your snapshot cash and UF is a big
cash so by directly manipulating this
object you can do some pretty cool
things and really improve performance
you can cheat it faulting if you've
gotten a row backs in the database using
raw rose or one custom used some custom
jdbc code writing rod jdbc code he
implemented a cursor pulled that stuff
back and now he sets those roads into
eos it records the snapshot
called salt for global ID and it's good
to go you can also preflight a to many
relationship this is a pretty readable
for inserted years since 30 years begin
life with a too many fault and most of
the time that's salt when it goes to
database they aren't going to be any
records there because it's a brand new
yeah sometimes it could be if you've got
multiple writers but for the most part
those relationships tend to be empty but
EF doesn't know that so the first time
you touch that fault you modify that
newly saved object it's going to fire
going to go to the database and it could
be there could be a lot of records there
so you might want to just skip that and
you can use record snapshots the source
global ID to do that and to refresh it
too many snapshot a lot of people ask
questions about this so passing null not
a blow away the snapshots for that too
many relationship and then it'll be
researched and you have to remember to
lock and unlock the object store a
coordinator and that's the one that's
associated with the database context
that's using this co database object
okay so we're going to spend some time
that optimistic locking now there's an
entire chapter on optimistic locking in
the new eof developer guide update
strategies and mostly the subject is
about dealing with multiple writers
affection same data basically is about
cat solidity and what to do when
multiple people change the same thing
and this can happen when you've got
deployments with multiple web object
instances if you're using a single
application you've got multiple objects
or coordinators they're going to have
their own channel to the database and
they can make changes they interact with
each other or you have external writers
telling we've got an admin app that's
doing raw SQL or something outside your
control so the material we just talked
about and data freshness is pretty
important in avoiding this problem
obviously if you don't ever modify scale
data you're going to be much better off
so you can tweak your fetch timestamps
to keep the data freshen up if you keep
the data to freshman new health
performance problems as you're always
going back to the database and you can
also implement code to propagate a
distributed notification our u.s. does
not at this time implement the Tribune
notifications itself there are a variety
of third-party solutions in here too one
from wire hose and once in project
wonder and they're both free
so you can check those out recovering
from this problem they think we have to
catch an ear general adapter exception
we're going to have a demo and I'll show
you where that is it's also in the
developer guide but basically that's
your hook for implementing a recovery
specific to your application because eos
doesn't know if you want to have the
first save win the last save win you
wanted to emerge it's really specific to
what you're doing the EU adapter
operation in the user introduction of
that exception is one of the most
important parts and got the attempted
road changes in operation type code so
inserted updated deleted or locked and
then the EO database operation has a
reference to the enterprise object as
well as the added sync stale snapshot
and as you're recovering from NASA
mystic locking exception keep in mind
that reef alting is going to remove that
ye o from the updated list so if it's a
deleted or updated object it's just
going to get reef altered and the
editing context is going to forget about
that and you can't result a newly
inserted Enterprise object so it's best
to basically pull out the deltas from
the enterprise object ree fault it and
then apply those Delta's again and in
the process of applying those Delta's
again to get any context emotes that the
object is changed again okay we're going
to go to demo to now and something new
in webs 5.2 is multiple channels to the
database you do simultaneous operations
we're going to talk a little bit more
about this later but basically you're
just creating your own object store
coordinator and we've got a new thread
here and I'm doing something pretty
simple just to show you how to recover
for an optimistic locking exception and
in my application constructor I just
create this new thread so first you're
going to want to do the save and catch
the general adapter exception and then
you're going to have to check the user
info a dictionary to find out whether or
not it's actually an optimistic locking
exception or something else entirely
so you can do that by getting this key
out of the dictionary and then checking
handy little method this is documented
but it is a little obtuse so go through
all this when you handle all this you
want to get the adapter operation out of
that user intra dictionary which has got
everything just sort of jumbled together
and from that adapter operation you get
the operation type code which you can
use to decide what you want to do as
well as a database operation here on a
database of operation has to your failed
deal you can get a delta fiction area
from the adapter operation and the
current snapshot from the database
operation and leave in this example I
just assume i'm using the sessions
default editing context but you can pull
the editing context off of banter prize
of itself if you want to and our
recovery mechanism is just last right
wind which is he here we grab the delta
above from the adapter operation you
result the object and this line we just
you've used for our component we apply
the changes and we'll go back and say it
again because it's a little loop
this is just using the real estate
example framework and housing prices
aren't really going up very much anymore
they used to be going out more and so
these are a whole bunch of things that
our background thread decided to change
while we were working at it it's pretty
much throw back the slide and next we're
gonna talk about multithreading and us
so there are a variety of good books
available about multi for Engine Java
and we can't really go into just general
multithreading in Java because that's a
pretty big topic concurrent programming
in Java by Doug leaves in my library
it's a pretty good book on there just a
zillion of them you probably wanna pick
up several so some necessary contact
concepts that we're just going to skip
over synchronize methods and synchronize
blocks tri finally blocks and the wait
and notify methods on object and then
the web Bob's expect them to Delta dock
be what's new area has more information
about locking issues specific to EOS job
applications are always multi-threaded
whether you like it or not the object
finalization thread so this has nothing
to do with objects the objects
finalization occurs in a separate thread
so if you have a finalizer those
finalizar methods are going to get
executed in another thread that's just
the way it is with web objects
applications is also the session timeout
thread and that's also going to be doing
eof operations and then their timers for
notifications long requests pages and
any threads you create yourself like we
did in the demo so here's proper used to
try finally just want to lock the
resource do to try use it you really
never want to mess with the lock object
itself it's extraordinarily difficult to
do properly it usually involves having
another lock object just to manage it
kind of Heisenberg effect so you pretty
much want to leave those alone so AOS
contract with you and this is again talk
to more about in the Delta doc is that
you have to launch everything that you
access directly it's just the way it is
the locking in addition to everything
else does how
keep us informed about what resources
using at any given time the NF locking
interface r is for all the objects that
support thread safe use objects who
don't implement NS launching like NS
raised and in s dictionaries you don't
have to protect yourself so you can just
create an NS recursive lock to do that
trilok is amazingly useful and it's
supported by NS recursive lock n do
editing context two of the main
interactions with locking and what this
lets you do is execute an operation only
if you're certain you won't block so
that's great you can queue up an
operation happen later if you think you
will block and it's used in the
notification delivery mechanism control
/ or killed s quit to the process ID
produces a stack trace of every thread
in the JVM and I can't recommend this to
highlight it's a phenomenal debugging
aid you get to see what all the threads
are doing the JVM will tell you which
locks they're waiting on it's really the
only reason I'm still here optimized it
in jaypro for both commercial products
they can help you debug multi-threading
issues and they also support memory
performance and cpu performance of
profiling so they're really great
products you can check them out the main
launch you're going to interact within
us is on the editing context this
controls all kinds of things now it's
true that nested editing context share
the same lock as their parent however
you still have to lock it this is the
contract that you have with us and he OS
has with you basically the only
consequence of this that you can depend
on as multiple threads can't come in and
use the same hierarchy of nested ending
context at the same time you can't cheat
is locking this way well you can try but
shared any context lock themselves and
they're the only objects in you have to
do so otherwise it just gets me a
nightmare to maintain them but basically
they're the only object and you have to
do this and it's really important to
launch everything else you always have
to launch the editing context before you
access any of its enterprise objects so
even operations you think would be read
only or sort of intrinsically fred space
they're not there's fault thing going on
behind your back there's a lot of
cashing in the frameworks themselves
it's going on a lot of transparent
operations to keep the object rest
maintained keep memory down you just
have to lock everything and the e
objects
coordinators will lock all of their
cooperating object stores if you ask
them the lock directly and those usually
give you a database context so what you
see here is a thread view of the EOS
snack the EO object store coordinator is
the focal point it's sort of the center
of mass for eos and it serves as a
mediator between the EO control and the
EO access layer this diagram is a little
oversimplified there call back some
delegates and stuff but this is your
basic idea of how threading work in EOS
and the obvious where coordinator is the
center of it all so multithreading an
eof there are a couple remaining
bottlenecks the critical sections and
your classes can be very small but if
you're doing something that does a lot
of models or entity work you're parsing
models or you're creating your own
models on the fly you should be aware
that there's some concurrency
implications there and the allows
concurrent requests handling swagg only
affects webobjects the web objects
frameworks not web objects and us this
affects how requests are dispatched to
both sessions and direct actions and any
other request handlers you have and it
has no effect on us like I said both the
object finalizer thread and the session
timeout thread are going to be doing us
operations whether you like it or not
and this is to deal with memory
management and snapshots and a bunch of
other things so it's really important to
keep the editing context lock properly
one thing I have seen some customers do
is they launched an editing conflicts
they use it to do one little thing and
then they unlock it you can lock it for
as long as you need to write if you're
not going to share that at any contacts
with another thread you can just keep it
locked you don't have to make the locks
really fine grained that's the point of
implementing these locks on these
objects is to allow you the flexibility
to control the grain of belonging so my
life might have purpose some stuff that
I learned painfully while working on us
non-parallel locks are like debt if
you've got more than three locks and
they're all somehow related you will
regret it intersecting locks increase
the probability of deadlock so the
Morlocks that any thread needs to
acquire to get its work done the greater
likelihood some bug is going to come
along and cause your application to
deadlock because some threads love them
in the locks in some threads with other
locks and this is a permutation that
increases combinatorially it's ugly and
unfortunately these apps tend to work
very well in development and not so well
in deployment under high stress after
many days so those are kinds of bugs I
like to avoid something a lot of people
don't realize is the synchronized method
and the synchronized block these are
their own implicit lock object and it's
on either that java.lang.object or the
java class that you're working on
depending on the kind of synchronized
statement so you can you can deadlock
with these and you can cross block with
the synchronized statement and an actual
lock object and if you come in and you
block inside a synchronized block you do
some IO or you try to grab a different
lock no other thread is going to be able
to do anything involving that object
with that synchronize so it's not gonna
be able to execute any synchronized
methods not even a little one line
setters and getters and it's usually not
what people intend to have happen so if
you're going to lock for something that
you expect my clock like either
acquiring a new lock doing some io
something expensive you should do it
outside a synchronized scope and you can
use the NS recursive locks I prefer that
because it allows you to use the tri
finally syntax regardless of what the
call stack looks like so you can just
keep invoking methods recursively or not
or to use java's we can notify protocol
if you should comfortable that okay so
we're gonna talk about a new feature in
web barbies 5.2 into concurrent database
access and that's putting all those new
threads that you learned how to create
to use and to do a bunch of things
simultaneously with your database as a
diagram showed the EO object store
coordinator is the root of everything in
the eof in terms of threading so each
EEO object store coroner has its own
stack underneath it also in set a lock
with own database channels and its own
snapshot cash so they're extremely
independent notifications between them
don't hold our notification there are no
notifications in between them so they're
very independent
it's pretty easy to do just create a new
one pass it on to the constructor for
your editing context you can also change
the default object store coordinator and
I believe in project wonder there's now
an object or coordinator pool you can
use so you can use these independent
snacks any way you'd like but there are
some benefits to using roro operations
with these stacks and that's there's no
overhead from duplicated snapshots so
there's less memory use and you're not
worried about propagating notifications
the actual concurrency is throttled by
your database so you have to make sure
that your database is set up to keep
adding more channel all right and we're
on to raw rose so these are the lowest
level operations you can use an eof and
they allow you to bypass the entirety of
control layer they'll return a result
set in NS array of nsdictionary and each
roro is itself an nsdictionary there's
no object grass management no undo redo
no relationships no faulting which may
be good and there's no Road Cashin and
you can use hand coded SQL so the EU
effects specification you can just take
a fetch specification you set this flag
and you'll get back we're all rows
instead of enterprise objects really
easy to do probably the best way to get
started you can also pass in the custom
SQL hint and this will allow you to
happen optimized SQL something specific
to your database or you can do something
that you won't generate automatically
for you my other favorite is raw rose
for SQL really easy to use and there
bunch of other areas in EOS where you
can interact at this level so some
things to keep in mind while you're
using raw rose is that both Enterprise
objects and dictionaries implement and
its key value coding so you can make
instance variables types to NFC value
coding the interface and then as you're
processing the results from either and
enterprise objects request a fetch or a
raw raw fetch those results can be
displayed in the same code so the same
code path can reuse them that's really
useful with low components or UI layer
work you can promote raw rose into full
ears as long
as you fetch the primary key attributes
and you can demote ears back into the
primary keys if you want to return to
bare metal work and the stink movies
example that ships with develop sticks
demonstrates these ideas so it uses the
primary key to do direct action based
work and there's no sessions so there
are a couple features of us doesn't
provide at this time and you can use raw
SQL to get through these features
they're pretty handy so there's in
qualification and null relationship
qualification or sweat sub queries and
again project wonder has got some of
these things built in for you for their
quarry operators for you and good reason
to go check it out and now Steve miner
is going to come up and give you a
demonstration hi thanks then all right I
have a demonstration here for how to
execute the sequel using the u.s. stack
I've written a little sequel tool that
just is similar to any command line tool
that you might get from your database
vendor the advantage to my tools I can
use it with any models and if I don't
have a local database centers sequel
tool I can use this to make changes to
my database or just to explore a little
bit on the data now before I get into
that I want to show you the code it's
very easy to execute a bit of sequel
first thing you need to do is you're
working at the EU access level not the
you control level so we're bypassing all
of the object graph we're going to load
a model it'll take this line here so to
load a new model you just need to know
the past your model or you can pick up
the model that's already been loaded by
us you can add that model to a group
that the model group you take a look at
that that's just a way of grouping
multiple models you probably use that
when you're developing your applications
the model group knows about all your
entities across the set of models you
have to make sure you don't have any end
named conflicts within your group so the
next thing you have to do is collect and
after give it a model you can always say
adapter with model that will instantiate
the adapter and that allows you to make
your connection to the database the
adapter context is your scope for your
transaction you don't have to interact
too much with your adapter context but
the adapter context also allows you to
create a channel and channel at the
adapter level is the entity that or the
objects that knows how to actually do a
query to the database so with that just
a few lines of code you can get set up
so you've opened the channel now you
have a way of talking directly to your
database I'm going to show you how the
sequel command actually execute the
sequel slide down so give them an
adapter channel there's just one line
here that's going to execute sequel your
sequel string is just a regular Java
string we have to convert that into an
expression that an adapter channel knows
how to use so we ask the adapter for its
expression factory and the expression
Factory has a method called expression
for string that expression converts it
into an expression then we just call
evaluate expression on the adapter
channel that sends a sequel to the
database we get back a result set our
results are going to be an array of
dictionaries so you can see here what we
do set up a mutable array we have to
tell the adapter channel what the
results said is going to look like I
want to take a minute to show you how we
specify that I'll come back to that in a
second once we've told the adapter
channels what the results that will look
like we call fetch row multiple times
until we get back and null each of those
rows of the dictionary we're holding on
to our own result set this way and when
we're setting up the result set there's
one method in the adapter channel called
describe results that's the ass
after you've made a query to the
database the database knows what the
results that will look like the adapter
channel has a method called describe
results that specialized for whatever
adapter you have to be using it will
create an NS array of EO attributes so
if you're doing raw sequel via the
adapter channel doesn't know anything
about any particular attributes we have
to sense the synthesized make new
attributes on the fly to describe each
of those result columns that are coming
back now one thing in normal US
operations we never have any name
conflicts but we're doing raw sequel
your result dictionaries are going to
use the column labels that the database
gives us in sequel the there's the
results are returned by position so
there's not any problem with name
conflicts but if you're doing some
complicated join and two of those
columns have to have the same name when
we turn that into a dictionary we're
going to smash some values because we're
going to be using the same tees so I
have a few lines of code here just to
walk through the result set and change
the attribute names if there's any
conflicts we can also use that a bit
later to manipulate the result set so
it's more convenient to use when you
want to turn things back into really
owes all right so that's enough coach
look at that again so now back to the
demo this command line tool you can just
type sequel to it it executes sit
there's a few other commands that knows
about in dealing with your model for the
demo purposes there's a command that I
called mo that's in a load the commands
from a text file so that way you won't
have to watch me make any mistyped so
one reason you might want to use sequel
is if you're generating some kind of
report you're doing something with
sequel aggregate functions or you're
doing a complicated query that eos
doesn't have a facility or a way of
expressing if you're doing in this case
we want to get the the minimum value for
revenue the maximum value in the average
out of the movie table so we execute
that we got back just a raw row that's
the diction
re and then you can see to the labels in
each of the results for display purposes
I'm just running down the dictionary
showing you the keys and the values okay
another common thing is fast for a count
count stars kind of a special aggregate
function in sequel in this case we want
to take a look and find all the movies
that start with the letter C so we're
going to get back just as a result a
single dictionary or dictionary single
entry that's the count you might do
something like this if you want to
customize your user interface according
to how big the results it is if you just
have a few objects we might display it
one way if you have millions of objects
you might want to do something different
okay we're going to come back to this a
little bit later I want to show you a
bit of a trick way to do this by saying
in the normal object world using objects
with that's fetch specification this is
how you do it in straight sequel alright
so now in we fit we figured out what our
count was now we want to actually go out
and get some bits of the those movie
rows in this case I'm asking for the
movie ID and for the title that's useful
if you're doing some kind of display
list we're getting back these
dictionaries or not folios we're not
keeping any snapshots here but you can
put up a display of all the say titles
and because you're saving also the movie
ID you can convert those back into eos
later okay so those are pretty simple
sequel examples you probably wouldn't
need to execute straight sequel to do
that but more complicated query in the
eof world is in this case fine find all
the movies that have no director I want
to take a second go back to you a
modeler and just remind you what the
model looks like for movies is our basic
examples that we have a movie table and
it has basically a many-to-many
relationship with this with the talent
table so any movie could have multiple
directors and of course any director
could direct multiple movies so when
you're modeling that in a sequel
relational database you need a
correlation table this case we called it
director so a director is just a pair of
the movie ID and the talent ID
that allows us to form the many-to-many
relationship I'll go back to our sequel
so the question is how do we find all
the movies to have no director if you're
doing that with a normal set
specification well we have to write some
code actually an eof we have to get all
the movies check each of their directors
too many relationships find all all
those with the count is 0 and that's
perfectly easy to do but if you have a
large data set that's going to do a bit
of work in fetching all that information
from the database and in sequel you can
pretty much do that that sort of thing
in just one query here i'm doing a
sub-query and using the sequel in
operator so we want to find out all the
movies that have a movie ID where that
movie ID does not exist in the director
table that's the same thing as saying it
has no directors so we can just execute
that directly and again I'm getting the
title back just for display purposes the
main thing if you're doing something
else with a neo is to get back that
primary key which is the movie idea here
alright so that was that was a fairly
simple query a little more complicated
query you want to find all the movies
that have more than one director ok this
is a good one for all these sequel
experts out there you can think about
this a bit I came up with this line of
sequel what i'm doing here is joining
the director table in the movie table
that basically kind of gives me all the
director movie pairs then I'm for each
of those directors that have directed a
movie I'm looking in the director table
for anyone else who directed that same
movie okay I'm taking account of all
those talent IDs where those movie IDs
match and that's in a sub-query that I'm
that I'm comparing that so I'm saying
greater than 1 because I want to find
all the movies that have more than one
director ok this would be take the same
kind of loop if you're just writing
regular eof code you have to go fetch
all the movies such all the directors
and check their account so here we have
6 results again I just fetched the
titles new movie IDs now given any
primary key of course you can go select
the right row here I want to
like the movie and given my primary key
so 111 let's see what I get this is a
raw row now I just I said select star so
I don't when I say select star I don't
really have much control over the label
in that dictionary okay the database is
going to decide what labels to use we're
translating those labels into the keys
for the result dictionary now you may
notice that it's using all capital
letters that's typical for sequels
labels are all caps when I want to turn
this back into a movie EO I need to have
a dictionary a primary key dictionary
that matches the name of my attributes
that was used in the primary key so I
need to change the key and what I've
done here in my little application I've
kept a small dictionary where I can do
key mapping so I'm gonna say okay
whenever you give me a result set map
that uppercase movie underscore ID into
movie ID that will give me a good result
alright so I'm just going to execute
that again and you'll see the only
difference here that matters right is I
have a key here underscore movie ID now
another way to do this often is equal if
you're specifying your whole select list
you can you can say what label to use
for any particular column is coming back
and so you might just put a label their
call it movie ID put it in double quotes
so you control the case that way but
people have had a problem when they're
doing raw rose sequel sometimes they're
doing a join they get either name
collisions or they get the wrong case on
something so in an upcoming update
there's going to be a new version of raw
rose with sequel that gives you an extra
parameter where you can specify the
mapping for all those column names that
might make it a little easier to use
okay so we said we said before we can
select with sequel to get things but you
can also do a lot of this kind of stuff
just in regular us using such
specifications so i want to show you
here out of how to fetch an object using
primary key let me go back to the model
and show you a fetch specification
alright so in deep fetch one movie this
is used to think movies example we're
doing a qualifier the space on the movie
ID and we have a qualifier variable in
this case dollar sign my movie so when
you use this specification you need to
have a binding for that qualifier
variable you can think of this this
fetch specification is kind of a
template so when you bind something to
it you create a new page specification
we're using movie ID now if you remember
movie ID is the primary key for the
movie entity but it let me go back and
show you the movie entity movie ID is
not marked to the class property okay so
that's that's maybe not obvious to
everyone but you can qualify over
attributes that are not class properties
long as they're in your model we know
how to map things with your entity
alright so we have a simple fetch here
we're fetching all enterprise objects
let me execute this command EO is a clan
that's built into my little tool it
basically just called the object of
primary key value and does a real fetch
in the display here I'm fetch it I have
a real movie and we're showing the
primary key and I'm throwing all the
attributes of course the the advantage
to getting really owes is you can use
key value coding here I'm going to fetch
the that same movie and then you apply
the key value coding studio name and it
executed that got that EO found the
studio which is another AO and then went
and got the name out of it so that's
much easier than writing all the sequel
to go get that particular name now I
want to show you another fetch the
qualifier variable
sorry okay so this one's just the
explicit with a deep fetch the V fetch
is doing the same thing as my other
commanded coming back here I have
another such specification this one is a
raw fetch specification so I'm getting
an attribute called Z count I'm going to
take a look at that in a second in how
that was modeled qualifier is checking
the title so its title like my title my
title is gonna be some pattern that we
have to bind to now remember we're
fetching Z count we're doing a raw fetch
so we're not getting back folios we're
just getting back a value for Z count
and if you look at movie the count is
matched that's not a class property so
it's not part of your EOS class but it's
defined in the entity and our definition
for that is count star so we're going to
use that sequel expression count star in
the fetch specification when we execute
it so this is an alternative to using
raw sequel and it keeps you in the
normal us fetch specification world it's
a little bit easier to maintain than
executing your own sequel so I'm binding
sea star to my title now I'm gonna fetch
using that count for title like so I
found out that there's five movies on
that count and again this is this is a
way if you're have to adjust your
interface how big your results that is
it might make sense you want to go find
account first and just to show you if we
can fetch those same movies once we have
them we know how big it is i'm doing a
raw fetch here just to get the movie ids
and displaying it alright so that's
that's the end of my demo here the what
i want to do is get you give you a feel
for the fact that you can execute any
sequel you want it's good for generating
some kind of reports or complicated
queries but for other things you want to
take a look and try to use objects of
that specification when you can thank
[Applause]
thank you Steve so today we reviewed
memory management data freshness
optimistic locking multithreading an eof
concurrent database access and raro
operations I note about the forthcoming
webobjects five point to point to update
the main focuses of this update is on
Mac OS 10 server and j2ee integration
particularly jboss but there's some eof
impact some goodies here like log4j
support and some J&E I look up for your
application properties as well as a
sorted bug fixing so the apple technical
publications group has got tons of
documentation and this is the stuff that
I use I'm particularly EF developer
guide and the 52 Delta doc are both very
important and the API reference
reporting bugs bug reports apple com if
you don't file it we won't know about it
probably project wonder lots of
interesting extension CEOs as well as
just some general idioms already
implemented for you for java programming
and us programming and some third-party
sites the omni group and stepwise sites
they've got mailing lists community
resources and technical articles both on
web objects and on us who to contact web
objects at apple com goes to a bunch of
people you can also use bug report that
up as I calm and there's enterprise
level services and consulting support if
you want to hire an apple consultant and
here's some stuff that somebody else but
you should know about
you