---
title: WWDC2003 Session 616
framework: wwdc
role: article
path: wwdc/wwdc2003-616
---

# 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
