Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2001-610
$eventId
ID of event: wwdc2001
$eventContentId
ID of session without event part: 610
$eventShortId
Shortened ID of event: wwdc01
$year
Year of session: 2001
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC01 • Session 610

Introduction to Data Modeling and Connectivity

WebObjects • 1:01:09

This session demonstrates building EOModels for connecting to databases via JDBC. Learn the basics of creating entities, attributes, and relationships, and explore advanced topics such as custom attribute types and modeling entity inheritance. This session also covers using LDAP as a datasource.

Speakers: Steve Miner, Ernest Kim

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

I want to welcome you to Introduction to Data Modeling and Connectivity. I'd like to introduce Steve Minehr. Good morning. Thank you for coming. My name's Steve Minear. I'm a WebObjects engineer. I don't have any songs for you today like some of our other sessions, sorry about that, but my mother is Canadian, if that helps.

So, as an introduction, we're going to talk about two major things today. First, using EOModeler to map relational data into Java objects. And then secondly, we'll be talking about the JDBC adapter, which is our main adapter for WebObjects 5. So, before we get going, can I ask how many people have used WebObjects and used EOModeler before? Can you raise your hand? Okay, so most of you have seen this. This is an introductory talk, so there might not be that much new for you. If you need some extra coffee, you can grab it now. Come back for the second half and find out about the JDBC adapter, which is new for WebObjects 5.

Okay, what you'll learn. We'll talk about, first of all, model, what a model is, how it contains entities, attributes, and relationships, and we'll explain how you create those and what they mean. And we'll talk a bit about fetch specifications, which is how you query the database, pull objects into your application. We'll talk about entity inheritance, how to model inheritance, some of the pros and cons involved in inheritance. And finally, we'll talk about the JDBC adapter.

This slide, if you went to the introduction to Enterprise Objects Framework, this slide is supposed to encapsulate that whole hour in one slide. Okay? So at the top, we have a database view of data. So that cylinder is a... tabular data we have rows and columns in there so we're using Neo model to define how we translate from the tabular data in the database into our object and that's matching up columns into attributes and taking the rows and creating dictionaries first and then into real enterprise objects so the what we're trying to suggest there is we have to do some type coercion to go back and forth from the database native types into the proper Java types and the types that we use in EOF and web objects and finally at the end we get the EO and the EO is enterprise object is what you want to interact with it'll be living in an editing context and for most web object applications all you have to worry about is your EOs you're not too worried about your database but we're talking about in this talk how we set up the model to do this mapping so you don't have to think about it anymore once you're once you're writing your application code So what is an EOModel? Well, it's, if you're familiar with entity relationship diagrams, it's a tool that, or a model is an object that does the mapping for you.

It describes both the relational data and the object that you want to transform that relational data into. We declare entities, which does a mapping from a particular table into particular objects. The connection dictionary defines how you make that connection to your particular datasource. And we'll talk more about what goes in a connection dictionary later.

Stored procedures are also declared in a model. There are places where you can use your database's stored procedure to fetch rows back from the database and create EOs that way. Or sometimes you might want to be doing deletions. So if you're using a special lead or some special logic that's already been encapsulated in your database, you need to use that because whoever controls the database doesn't want to give you direct access to the tables.

And finally, we have named fetch specifications. So a model can contain pre-built fetch specifications. And if you went to the introduction to EOF talk, you learned more about fetch specifications. We'll talk about how our EOModeler tool can help you create those fetch specifications. You already know how to use them if you went to the other talk, and we have a lot more information in our documentation about using fetch specifications. All right, so for our first demonstration, we're going to bring up Ernest Kim, and he'll be running EOModeler just to give us a view of our sample data.

So for this first view, we're showing a diagram view. We'll get into more details about EOModeler in a minute, but just give us something concrete to talk about. We've created a very small database, just a few entities and a few relationships. The idea here is we have a course entity, which represents a course that someone's teaching in school. There's some professor who's the instructor for that course, and then there are students who are enrolled in the course.

This diagram view is showing, first of all, the different entities, which are in the boxes, the attributes that belong to those entities, and then the arrows are suggesting the relationships between the different entities. There's a lot more you can do in the diagram view. You can control which things are labeled, which attributes are being viewed. There's different ways you can filter this and save layouts. But for our purposes right now, I think this gives you a general idea of what we're going to be talking about, and when we do something concrete, you'll understand that we just have a few entities involved.

There's also some inheritance. This person is really an abstract superclass or abstract entity that some of the other entities, the student and professor, are going to inherit from. We just want to show you that for inheritance. This might not be the way you design your school administrative system, but it'll give you a suggestion of what you can do in EOModeler.

So what is an EO entity? Well, at the basic level, we map a table into a class. So you have a database with your rows and columns, and you have a Java class. You have to declare how you take that raw data and turn it into an EO. Then EOF does all the work for you.

So there are various aspects and settings you can put on an EO entity. First, you can mark it abstract. Abstract means that you're never going to actually instantiate an object of this class. It's just there principally for inheritance. There can be a parent entity. Again, if you're using inheritance, one entity can inherit from another. It'll get all the attributes from the parent entity.

The restricting qualifier allows you to filter the rows from a particular table when you're fetching your entities. So we also use this when we're modeling inheritance. Basically, instead of saying, "My entities are every row in this table," we put some kind of qualifier on that and it restricts it to a subset of those rows. We'll talk about that during the demonstration.

You can also mark an entity as read-only. Depending on your application, that might speed things up a little bit. That means we'll never be writing anything to that entity. It's really just there for some kind of bookkeeping purposes. You've already pre-built everything. And you can cache an entity.

That changes the behavior of EOF a bit where we know we have everything in memory that we need. We can do searches in memory instead of going to the database all the time. But the last two are used just in special circumstances. In general, your entities will not be read-only and won't be cached, and you'll be wanting to write data back to the database.

All right, so let's go back and look at EOModeler and we'll take a closer look at entities. So this is the way we typically open up EOModeler. The model name is at the top left of the tree view. Then we have a list of entities down below. Over to the right we have a table which declares the entity names, what table it goes to, and what kind of class you want to instantiate. And by default we'll give you an EOGeneric record, which is our convenient holder of data. It has no particular business logic. In most of your applications you'll be creating your own special class to hold your EOs, and you'll have some business logic associated with that.

Okay, so now we've selected the course. So in the course you can see a list of entities and relationships to the side. We'll talk about those more in a minute. I like to browse some data. So what Ernest just did, he clicked on the icon that looks like a database cylinder with a little magnifying glass on it. So that's browsing data. This is a good way just to test that your data is there. You set up your model. It's an immediate validation that things look right for talking to your database.

And you can see what kind of values you have in the database. Here you can also, just for your convenience, you can have a qualifier and filter this list. So if you have a lot of data and you just want to take a look, see what's in there, you might do some experiments here. So Ernest is adding a qualifier, title like F*. So star is the wild card.

So now you see there's only one course in their formal logic which matched that F*. You can wipe that out, have an unqualified query, and we'll get all the classes. So for our demonstration here, we're only using two classes. It's a very small database. Let's show the inspector on the class.

So this is the first panel. There's multiple panels in our inspectors, and it really pays for you to spend some time playing EOModeler. Make sure you go to the inspector on all the different types of model objects. There's lots of settings you can change in the different inspectors, and it's worth spending a little time experimenting and getting to know what all those different things mean.

So in this first panel, We have the name, the table name, the class. Those are all immediately available anyway in the table view. and then we have a list of the properties. And this is just another way of editing. You can do all this work in the table view also. We'll talk about the different properties a bit later.

So now we're looking at the professor entity, and we're looking at the second panel, the advanced entity inspector. And this entity uses inheritance. So the first thing you can notice is in the parent box, We've selected person and there's a little mark there indicating that the person is the parent for the professor. All your other entities will be listed here and only one of them will be selected as parent or maybe none if you have no parent.

And then the other thing is because of the way we're setting up our table with single table inheritance, which we'll talk about later, we have a restricting qualifier. So when we fetch The professors out of the database were going to be hitting the person table, and we're only interested in rows that satisfy this qualifier where ptype = 1.

So an EO entity contains, first of all, a whole list of EO attributes. And each attribute is mapping a column into an instance field of your Java object, or an IVAR if you're used to the Objective-C. Now you have several aspects to an EO attribute. The first thing to consider is whether or not this attribute is a class property.

A class property of your EO means that when we fetch from the database, we want to fetch this column and create a corresponding value in your EO for that column, or for this attribute. If it's not marked as a class property, it's there so that we know what to do when we're generating SQL, but it's not declared as part of your class.

Many things that you put in there, especially foreign keys or primary keys, you wouldn't want to mark as a class property because it doesn't really contribute to your business logic. You're not going to be using that value when you're programming or creating your EOs. But EOF needs the primary keys and foreign keys for when we're creating SQL and doing some of the bookkeeping for you when we write values back to the database. So those attributes are declared, but they're not marked as class properties.

The next one is a primary key. A primary key is a special attribute that uniquely identifies this row in the database or this EO in your editing context. We use the primary keys when we're creating what we call a global ID so that we always know how to get to that EO again. And again, when we're doing faulting, we need to know that primary key so that we know when we need to get this object, we'll be able to go to the database and fetch it.

So the next aspect is allows null. And this corresponds directly to what the databases allow you to do. You can mark an attribute whether or not it allows null. If it allows null, then if you don't set it, we can write a null into the database. In some cases, you don't want to allow null. You want to insist that your user has set a value there or that your application logic depends on having some value in that attribute. So you mark it, you leave it off so it doesn't allow null.

The external type is the type that the database is using. It's the type name that's specific to the database. So Oracle might have a varchar2. Not every database uses that term for the external name. So we need to know those external names for when we're creating tables for you.

Most of the time, if you've done reverse engineering, you don't have to worry too much about the external name. But if you're switching from one database to another, your set of external names might be different. And it's worth knowing what database you're talking to so that you get those external names right and you understand the details about the meaning behind different external names. Not every database treats even the similar terms the same way.

The value class is the class that you want this attribute to be expressed as in your EO. So when we talk about a VARCHAR in the database, the external type is VARCHAR, in your EO, typically that would be a string. So we have mappings for most of the common value classes. We'll declare something number and map it to the appropriate number.

The value type is the other column that helps us determine exactly, in the case of numbers, exactly what type of number to instantiate. So that might be a small i, meaning integer. Some things are ambiguous if we just are saying we're mapping to number. We need to create a concrete class of number, and the value type will help us do that. There are also a couple of other cases where the value type has special meaning to a particular adapter.

But maybe these things are attributes, aspects of attributes that you use less often. You can mark an attribute read only. That means you don't intend to ever modify it. And we will, EOF will raise an error if you do try to modify it. You can have custom formatting.

So you can have special format strings that define how you get the values in and out of the database. I think this is used less often. But. There may be some special cases where the values were formatted a strange way, and you really want to store and retrieve things slightly differently.

The derived attribute is almost a whole other kind of attribute. Instead of mapping just directly to some column in the database, you can have a SQL expression. So when you're fetching, you can have some combination of logic that is evaluated at the database, and we pull a value out of that. Usually, we can't update that value.

So if you have some kind of attribute, say salary, which is multiplying some monthly salary by 12, you could have a SQL expression, monthly star 12, and we'll fetch that for you and do the calculation on the database side. So there can be an advantage there. Or if you need some special function that exists in SQL that is inconvenient to program in Java, you can do that with the SQL expression. with a derived attribute.

Flattened attributes are attributes that belong to a different entity, but we've crossed a relationship to get to this particular attribute. And we want to think of this attribute as belonging to our EO, even though in our model we're actually storing the value somewhere else. So when we see more about relationships, we'll see how that fits in.

But you can imagine an alias that we've crossed one relationship, we're getting the value out of another table, but we're storing it and treating it in our Java object as if it were directly part of that. So it's a way of changing the model to fit your application logic, even though your database layout may be a little bit different.

And Custom Value Class is a capability for mapping the raw data from the database into some more sophisticated object that isn't, well, that is defined by you and your application. It's not one of our standard objects such as string or a number. It's something that you're defining. You want to do a mapping from our raw data into that. We're going to talk about that more in a minute after the demo. All right, so let's go back to EOModeler. We'll go back to the computer.

Okay, so we want to talk about attributes, and we'll review some of the terms here. So we've selected person, and we see just three attributes. The first thing, the first column in the attribute viewer is a little key icon. I'm not sure if that's clear to everyone, audience. The key indicates that this is a primary key. And so we're using person ID. And this is pretty typical, I think, that you'll have some kind of number or an integer as your primary key.

It's not a class property. So the second column is that diamond, is indicating which things are going to be mapped directly into my EO, what things can I use for my business logic. In this case, the person ID is really an artifact of how we store data in a relational database. It's not something that you need typically to worry about in your business logic, so we won't mark that as a class property.

The next column is the locking bit. This determines when we're doing optimistic locking, when we've made an update or about to make an update to the database, what values do we want to check to make sure nothing's changed and that we're safe to do this update. So EOF, as you probably have heard from the introduction to Enterprise Object Frameworks on Tuesday, keeps snapshots of all the data that we fetch out of the database.

And things that are marked for locking, we're going to check. When you do an update, we're going to check that all these other things that you marked for locking are still the same value in the database. If someone else had changed that row in the database and we're about to update it, our update will fail because of the optimistic locking. And that is determined by which attributes you care about.

Most of the time, you want to lock on all your attributes because you want to be safe and make sure that your application is only writing data that it fetched and it's in complete control of the database. There may be some attributes that you don't want to lock on, particularly blobs or any kind of large object.

It's very expensive to compare those. It turns out we can't generate SQL to do the comparison. For normal attributes, in our where clause, we'll generate the SQL and make sure that we're updating the right row for you. But if you have something that's a blob, a large kind of object in your database, EOF is forced to pull that all into memory, do an in-memory comparison of that blob, and then do the update to be safe. And you don't normally want that. It's really bad for performance. So if you have anything that's large, I would say don't mark it for locking.

Then we talked about the value class and the first, so we have string and number. Number in Java is abstract, so we have to... Let's say something more particular about what number to instantiate. So the value type, in this case we have a little i, meaning let's transfer this as an integer. And we're inheriting this concept really from our Objective-C days where we needed more information here. We're still doing the same kind of thing in our models. We're still storing some Objective-C information even though we're doing pure Java for our EOs.

The external type we talked about, so we have two examples, the VARCHAR and the number. This is going against an Oracle database, so the VARCHAR2 is the Oracle normal type to use for VARCHAR. Some different, depending on your type, you might have a width or you might have a scale and a precision. There'll be other columns you can fill out for those.

Just for your information, when people first look at modeler, sometimes they don't see everything they want to see about particular aspects of the attribute. There's a little pop-up menu down there to the left. This controls what you see in EOModeler. So as you can see, we can, let's show allows null.

So now, that column there with the zero is the allow null column. You can make that disappear if you don't want to view that. Usually if setup allows null, you don't need to look at it all the time. If you hit the delete key when that column is selected, it's being hidden. We're not taking anything away. We're just hiding it from you.

When you're first using EOModeler, sometimes this is a bit confusing since your model looked one way and you've done some things to rearrange it. It might not come back the same way you expected. Or you might not be able to find things. If you get in that situation, use the popup or use the inspector. Most of these values are available in the inspector.

So we talked a little bit about the custom value class. That's another aspect to an attribute. And what this does is maps your value into a particular class. So this is at the attribute level. This is just a value in the attribute. This is not talking about an EO. This is just a custom class for holding some value of your attribute. So if you're doing this, you need to have a factory method.

So in this, this is an example. It might be called, if your class is called custom, you might have a factory method called custom with string. The idea here is a string will be passed. This is a string that we've pulled out of the database. We're passing it to your method. Your method will give us back one of your custom objects. So you'll just map this in the inspector.

You need a conversion method, so when we're writing things back into the database, we have your custom value. EOF doesn't naturally know how to put that into the database. You'll tell us to use your method, in this example, custom as string. We will send custom as string to your object. Your object has to respond to that and give us back a string. Then we know how to put the string in the database for you.

And the third aspect to a custom value class is the init argument. For the init argument, we've been doing an example where your init argument is a string. It could also be an NSData, if you have some large raw data, we'd map it to NSData, or a Java byte array.

All right, let's talk about EORrelationships. A relationship basically maps a foreign key into another object. And we saw earlier how relationships were formed. We described them in our diagram view as arrows from one entity to another. You've probably seen in other talks where you match up a foreign key to a primary key in another table.

When we talk about relationships, we're talking in EOF about a one-directional relationship. So we say to one or to many. A to one is a relationship where the destination is a single object. So in our example, a course has an instructor. So the course has a to one relationship to the instructor. There's just one instructor for our course. A to many relationship is where the destination is actually an array. of other objects.

In our example, a student might be enrolled in multiple courses, or a professor might teach multiple courses. In those cases, we'll create the array. We need to know the destination type, but we'll create an array of those objects for you. And typically, EOF works well if there's an inverse relationship, so something going back the other way.

There are several places where EOF wants to figure out how to make an update going back from the destination object into the source object. And it's pretty natural when you're modeling things to think of some of these relationships as a pair of one-way relationships. So you have an inverse for most relationships. But that's not required.

So we have a little diagram here where you can see the course has one instructor. The donuts are the EOs, and I think that's very common notation, graphical notation in our documentation. The arrows represent the relationships. The little box of two things is an NSArray, and you can see how the courses map.

So then advanced relationships, some other aspects you can set on a relationship. The first thing to think about in your relationship is, is this optional or mandatory? Do you require, to have a fully formed EO, do you require that it has some connection across this relationship? Does there have to be a destination value, or can it be null? If it can be null, then it's an optional relationship.

If you require that there's some value there for your business logic, and just for your, the semantics of your application, then it's marked mandatory. And EOF will enforce that. If something's marked mandatory, and for some reason your code or your user doesn't set a value there, EOF will raise an exception.

Propagate Primary Key is another aspect of a relationship. And what this says is that when you're inserting a new object at the destination of this relationship, It can inherit a primary key value from the source object. Now, this is something you have to think about. Typically, you want your objects to have independent primary keys, but there are some cases where it's very convenient to propagate the primary key, especially when we're doing some kind of correlation table and setting up a many-to-many, and we'll show that in our live demo.

The delete rules tell EOF what to do when you delete an object. There are a couple of different possibilities. We'll talk about those in a minute when we're showing the live EOModeler. But you can imagine one possibility is just to cascade the delete. If you delete a source object, you want to follow that relationship, delete the destination object, and so on. Another possibility is to nullify. So if you're deleting the destination object, the source object just wants to get a null marked where that relationship used to be.

Owns destination implies a stronger bond between the source object and the destination object. In fact, it's so strong that if the destination object is not part of this relationship, it has no reason for being, and it's going to be automatically deleted. This can be very convenient to keep you from having to write too much business logic.

If you set a new value for the destination of some relationship, the old value will just go away without any extra code on your part, if you've marked the relationship owns destination. But there are other times where you don't want to do that. You don't want to automatically delete things. You want to control that, let that object live for some other reason.

And finally, batch faulting. Now we haven't talked about faulting, but if you've gone to any of the other EOF talks or maybe some of the other WebObjects talks, you may know about faulting already. And most of you, I think, have used WebObjects, so you understand. The idea of faulting is a fault is kind of a placeholder object.

When we fetch the objects to begin with, they have relationships to other objects. We're not going to fetch all of those objects and recursively load up the whole database into our editing context memory. What we do is we fetch the objects that are immediately desired from the fetch specification.

Then for all the relationships, we put in placeholder objects, which we call faults. When you touch a fault, it will magically become the EO that you want to use. So your business logic doesn't have to worry about faults. But when we're creating these objects, it's important that they're marked specially as faults, and there's some performance issues about pulling in the faults. If we touch a fault, we have to make one round trip to the database to bring the values back.

It turns out it's very common that when you touch one fault of a certain type, your application typically might touch several other faults of that type. So to make that perform better, we have a concept of batch faulting. You can set on the relationship how many of these faults you want to bring back at once, and we'll make one round trip to the database, and maybe you marked it for 10 as your batch faulting. It's kind of a hint to EOF, "Okay, if you hit this fault, bring the next 10 with you." That will improve performance in many cases. All right, let's go back to EOModeler.

And we'll take a look at some of the relationships we have defined in this model. Selected student. A list of relationships here. First, Advisor is a 2-1 relationship. Let's inspect that. So in the inspector we can see the destination entity is marked as professor, it's marked as a 2-1, and the joins tell us which columns or which attributes we're going to use to match up those values. And you can see how that maps directly into the SQL we have to generate. For a 2.1, the source object holds a foreign key into the destination object. So at the destination side is typically the primary key is what you want to join on.

All right, so now this is showing a to-many. The destination is enrollment. Enrollment is really a correlation table. There's not that much interesting about enrollment, but it's a way of forming the many-to-many relationship between students and the courses they're taking. So our purpose here is just to form the, we want to form the to-many.

We're going to use this to flatten another relationship. On the student side, the source for the join is the person ID, and the destination side is the student ID. So the enrollment, if you think about when we saw the diagram view, the enrollment had a 2-1 relationship. The inverse of this was back to the student.

So this is a little bit simpler. We have a definition. It says to enrollment, dot to course. So what we're doing is we're following the first relationship to the enrollments. That will get us to an enrollment object. Then an enrollment object has another relationship to a course. By doing this flattened relationship, we make that jump to enrollments to course, and now the to-many relationship is actually an array of courses for this student.

So when we're modeling this, what we cared about were the courses. We didn't want to think so much about enrollments. They're there really just to form the correlation table to map correctly into the relational database. But at our object level, we want to program and deal in courses directly from the student.

Okay, we want to change gears a little bit now, and we've talked about what's involved in a model. Now let's talk about how you create a model and tables. So the EOModeler tool can do what we call reverse engineering. Reverse engineering is a way of interrogating the database, finding out what tables already exist, and creating the proper entities and mappings for all the attributes. We do that automatically for you.

It's a good starting point. In many applications, you already have your data. Someone else has defined the data for you, and you're going to put a web interface on that. So you want to get access to the database tables, reverse engineer. Maybe you don't need all the tables.

You'll pick a list of the tables you want to use and let EOModeler create those entities and attributes. That's a good starting point. After you've done that, you'll want to go inspect your model. Maybe you don't need all the attributes. You'll take some out. Maybe you'll need to form some other relationships. You might want to flatten some relationships.

There's quite a bit you can still do after you reverse engineered, but it's a good starting point. It saves you from having to type a lot of detail that you already know and has already been declared in the database. Now, not everyone wants to go in that direction. For some applications, you're in charge. You get to define the data format.

So you might start with the EOModel and experiment a bit. You'll just create some entities, declare all the information you need, all the things we've talked about, especially the attributes and the external types, and EOModeler will generate the SQL that's necessary to create those corresponding tables. We'll show you that in a minute.

EOModeler can also create Java source code for you. So you've declared your entities, all your attributes. Your entities are going to correspond to a particular class that you want to use for business logic. Your attributes map into the instance fields of that class. We'll create the basics of the Java source. Typically, you'll start with that and then add more business logic.

And then the other aspect of EOModeler has a feature called schema synchronization. So schema synchronization, it's a way of matching up what's in your database to what's in your model and vice versa. It gives you some options about what to do with missing fields or additional fields. It's a way of synchronizing your model with your database.

So, editing a model. The typical things that you might want to change in a model. First of all, switch adapter. So you've done your application, you've used one kind of datasource. Let's say you started with OpenBase, and for some reason you want to change, you have another database server, an Oracle server. You want to use SwitchAdapter to modify your model to work with your new datasource.

In particular, when you do SwitchAdapter, even if you choose JDBC, which we'll talk about later, SwitchAdapter will work through your model, all your attributes, fix up your external types to map to that particular datasource. This is important. In our previous releases, people would have separate adapters, an Oracle adapter or a Sybase adapter. Now we're going to be using one adapter, but the mechanism for adapting or changing your model into a new datasource is still to use SwitchAdapter.

SetAdapterInfo is a simpler operation. At this point, you're just editing the connection dictionary. You're not going to make any other changes immediately to your model. So, this can be a little bit confusing when we're using JDBC. We'll talk about that in a minute. If you change your, if you just use SetAdapterInfo and change something that's significant about your datasource, it would be better to use SwitchAdapter to make sure that everything in your model gets changed.

And of course, when you're editing a model, as we've seen, there are lots of fields that you can change. You make all your changes to your attributes and your entities. Just use EOModel. Click on something, type something else over it. That's how you make a change. And use the inspectors. There's sometimes more information available in the inspector than we can show in the table view. So that's another way of changing information about your model.

And the final bullet is editing fetch specifications. We have a fetch specification builder built into EOModeler. You can associate fetch specifications directly with an entity, give it a name, and that's available to your code at runtime. And it's a very easy way to fetch other objects. You've already set up a fetch specification or a template for a fetch specification. You can use qualifier variables to fetch particular information that you want. So we'll look at the fetch specification builder in a minute. Okay. Let's go back to EOModeler.

So as we mentioned, for tables, we wanted to-- we have course selected. We want to show the SQL generation panel. There's a little SQL button. We'll turn off those two about dropping tables. But we're going to slide down here. You can see we've generated some SQL to create this table for you.

And then we're also generating some SQL, in this case to go against Oracle to create a sequence so that we can create primary keys using that sequence. And we have a little code here that's trying to figure out what the next value should be in that sequence, in case you already have data in your database.

We're not going to do it now, but there's a button at the bottom that says to execute the SQL. That would go create the table. We already have the table. If you already have a table created, Oracle will give you some errors. They're pretty soft errors, so you can just continue past that.

The tables button is a convenient way to check what's already in my database. And if you wanted to create something, you can see it kind of reinforces that things worked correctly if you click on that tables button and just get your list. When you're dealing with Oracle, of course, these tables belong to the particular user that logged in. Different databases will have different ways of deciding what the table space is.

Okay, so that gives you a general idea of what you can do for creating, and we talked earlier about reverse engineering tables. All right, let's get back and talk a little bit about EOFET specification. So, you use a fetch specification when you want to get data out of your database and create EOs.

It fetches objects from the database into your editing context by using, by filtering according to the EOQualifier that you assign to your fetch specification. And the EOQualifier, I think you've seen in the introduction to EOF, how you form an EOQualifier. It's a query language that's a simple kind of object-oriented query language.

You can use key value coding, have key paths involved in your qualifier. So we'll do the joins across multiple tables for you automatically. You don't have to think too much about where all your data is located. Just work at the object level, crossing relationships, and referring to attributes by their key name.

One thing you can set on a fetch specification is the notion of is it deep or not. And this has to do with when we're using entity inheritance. A deep fetch specification will fetch not only the entity that it's been assigned to, but also all the subentities. So in our case, we had person as the parent class for professor and student. So if you try to fetch person, we'll fetch all the persons, we'll fetch all the professors, and fetch all the students. And then we'll filter according to whatever your qualifier is.

We also use fetch specifications for shared objects. In the EO Entity Inspector, you can see where you can mark whether or not you want to move objects into the shared editing context when you first load up this model. I think we'll talk about this in the advanced EOF session later today. I think that begins at 3.30.

So if you're using shared objects, you'll want to use a named fetch specification. You might want to share all the objects of this entity, or you might want to filter that and use a fetch specification just to get certain objects moved automatically into the shared editing context. And finally, we have inside EOModeler, there's a Fetch Specification Builder, and we'll take a look at that. Select Professor.

If you hit the little plus sign there, it expands the professor. You can see all the relationships below it and the stored procedures. So the stored procedure has a slightly different icon. By clicking on that, we're showing the Fetch Specification Builder. And we have a Fetch Specification already there. We want to browse. Let's browse data and see what we get back.

So this was a very simple Fetch Specification. We just wanted to see all the professors whose name began with J. So we can change that easily. We'll close that if you want to... You can edit that, let's say we want a W. You can put whatever you want in there and go browse again. This is an easy way to test your fetch specification right there in the builder.

Let's take a look at some of the other tabs in the Fetch Specification Builder. We talked about Fetch Specifications in some of our other EOF talks. The sort ordering allows you to choose how your results are going to be ordered. So you might order by name, in this case, office, location, whatever. You can choose several of these different attributes and we'll order on those. You can even follow a key path and we'll order according to the results in that key path.

The next tab is prefetching. Now the idea here is when we're fetching some objects with a fetch specification, there are some related objects that we might know because of our application logic that we're likely to touch these other objects. So I told you before that normally when we fetch an object, we create a fault for the relationships.

If you set up prefetching, you can say, well, I really know I'm going to need that object, so don't just make a fault. On some of these objects, we want you to prefetch, we want you to go get the real object so we have that in memory as a result of this one fetch.

We might actually have to go to the database a couple of times, but we can group things and give you a bit better performance if you have prefetching turned on for things that you actually need. And that, again, would be following some kind of relationship and saying, get me that object at the end of this relationship whenever you fetch this fetch specification.

[Transcript missing]

and you can decide which attributes to fetch. We have a couple of choices there, whether we fetch all of the attributes as raw rows or we just fetch a certain set of the attributes as raw rows. But the usual thing is most of the time you want to fetch enterprise objects and have EOF do the special work to keep track of those objects for you so you don't have to think about updating your database. You just change the object, save changes, and everything happens magically.

The next panel, options. All right, so there's a couple of extra options you can set on a fetch specification. First thing is a fetch limit. How many rows? There might be a case where you only want to get so many rows, you're not sure how many are out there, but let's stop at some limit. When you're doing desktop applications, it makes sense to prompt on a limit.

You might pull back the first 100 rows and let the user decide, okay, I'll get the next 100. These other things about doing deep inheritance fetch, fetching distinct rows, basically adds distinct when we're generating the SQL, we'll add a distinct so you don't get duplicates in your result set.

We can lock the objects. I don't recommend you use that, but if you're, especially if you're doing a desktop kind of application, you really know you own the database. You can lock the database, the objects in the database whenever you fetch them. If you're doing a web application, you don't want to do that. It's going to hurt performance and it'll cause you other problems. So don't, don't lock your fetch specifications in general, but if you know that you need it, it's there.

Refresh refetched objects. Usually, if EOF already has an object and you run another fetch specification, getting back that same object, EOF won't do anything special because it says, we already have that. It's in our cache. If you set this, then what you're telling EOF is, well, when you fetch this fetch specification for me, even if I've already seen these objects and think I know about them, I want you to refresh them, give me whatever's in the database instead of what I already have in memory.

And finally, require all variable bindings. We didn't talk so much about variable bindings. In the other introduction to EOF talk, they discussed variable bindings. But you can set placeholder variables in your fetch specifications. So they're not fully formed at this point, but you're going to do a binding using your code. You'll set up a dictionary to bind those query or qualifier variables and create a new fetch specification at runtime. So that can be really convenient to use the fetch specification as a template for other fetches that you want to do.

Okay, and then the final panel is the SQL panel. And in this case, we can see the raw SQL that's going to be generated. You can decide for a complicated fetch specification, you could say, well, you know, I could optimize that. I could write better SQL than EOF. So if you can do that, then you say use the raw SQL expression. You give us an expression. It has to return the result set the same way EOF would have returned it.

I don't recommend you do this unless you really know that you can get the best result and it's much better than EOF can do. This is hard to maintain. When you change your objects, EOF will do the right thing with all your fetch specifications. But, you know, your raw SQL won't know the difference.

And you can also mark stored procedures to use to do your fetch. Instead of doing SQL at all, you might call a stored procedure. Alright, we need to talk quickly about inheritance. There's three kinds of inheritance. We're talking about entities that are inheriting from other entities. As we've already indicated in our example, we have a generic person, and then professor and student both inherit from person. So, vertical inheritance.

For vertical inheritance, at the database level, we're mapping all the columns that are common into the superclass. So we have one table for person, which is holding the person ID in the last. Then we're creating for a professor, which is a subentity of person, we have another database table, the professor table.

It has just the attributes that are special to professor. It also has to have the same primary key so we can match those up and do a join. But what's special for a professor is that he has an office. Student, what's special about a student is he has this advisor ID in the middle of the table.

So he can see what's going on in the table. So he can see what's going on in the table. So he can see what's going on in the table. So he can see what's going on in the table. So he can see what's going on in the table.

the database we're going to use that as the foreign key to map to our advisor object so for vertical inheritance which is kind of the most natural if you're coming from an object or a point of view everything that's common is in the superclass and then things that are specific are mapped to specific tables we have to do a join to create a real eo so we want to fetch a particular professor we have to fetch the parts of the professor that are stored in the person table and then the parts that are stored in the professor table join those up to make one EO for the professor.

Another way to do inheritance is to push those common attributes down into the other tables. So at this point, we call it horizontal inheritance. We've taken things that were vertical, pushed them down into, in this case, the professor table. Now it has everything associated with a professor. So it has the person ID, the last name, and the office, all in that one table.

So now if we're fetching a professor, we only have to fetch against that one table. If we're fetching a student, we have a separate student table. He has a person ID, last name, those are the common parts, and then he has a special advisor ID. Again, it's in that one table. If we're doing a deep fetch on person, which is, now we're going to mark person abstract, we might have had persons that weren't abstract.

In our example, person's abstract, so we don't have to worry about actually hitting a person table. If you might have generic persons, then we'd have to fetch against that table first, then we'd have to fetch each of the subentities individually, and join all those results back to do a deep fetch.

So that again could be a bit slower. A special case of inheritance is what we call single table inheritance. In this case, we make one database table with the union of all the attributes that might be anywhere in this hierarchy. By doing this, we can do a deep fetch by using one select statement against the database table. And then EOF has to figure out, as we're pulling rows back, well, is this a professor, is this a student, maybe this is a generic person. We can do that one select, pull them back, and figure out which ones they are, give you your result set.

So if you're doing inheritance and you don't have too complicated of an inheritance hierarchy, I recommend you use single table inheritance for performance reasons. You will have to leave some columns null, right, because even though the student has a row in the database, the student doesn't have an office. So that would have to be null for that student.

So you need to have a little bit of flexibility in how you're defining your table in order to make single table inheritance work. We've also added an extra column called ptype that's special for the database. That's special for single table inheritance. We're using ptype to declare exactly what type of value we have in that row.

So we're using a 1 to be a professor, a 2 to be a student. EOF needs some kind of restricting qualifier that we talked about earlier to know exactly how to create the right kind of EO for you. Okay, we're going to go back to the demo, and I think we have to be very brief here.

I think actually since we're running low on time, I want to save time for questions. So we'll just show this to you quickly and then I think we'll end after that. So we can see here, Ernest has brought up two different viewers on the same model. And you can see person has the common types just like our graph. The student has one extra attribute, advisor. The other things that are common to the superclass are actually, the other attributes are written in italic type to suggest that you're inheriting these from the person. So let's just inspect student.

So in this inspector, the important thing is restricting qualifier, ptype equals 2. That's how we distinguish. We're in single table. We pull an individual row out. What kind of EO should we create? We're going to use that ptype equal 2 restricting qualifier to know this thing is a student. It's not an generic person. It's not a professor. And you can see the parent was marked as a person. So that's how we're determining what we're inheriting from. You only had to add the advisor. You didn't have to declare all those other attributes.

So maybe we can just, let's just browse person and that will finish it. So if we browse data for person, you can see everything's stored in one database table. The p-type column is different. Worcester and Jeeves are actually professors, they're type 1, and Fink-Nottle and Little are students, they're type 2.

Okay, I think I'm gonna wrap up here. There's more you can do with EOModeler. I'm going to be in the lab after the talk and we'll have other people in the lab all during the day, so you can come experiment with models and ask particular questions about how you want to model certain objects.

Can we go back to the slides, please? Okay. We've run late, so I have to whiz through the adapter information. The important thing to know is for WebObjects 5, the JDBC adapter is the adapter. This is the one we're giving you. The nice thing about JDBC is it gets to all kinds of different databases.

We have... We have great connectivity because we're using JDBC. Almost every database vendor is delivering a JDBC driver. We can talk to that. We've done specific work with Oracle and OpenBase, but other things can be added to our JDBC adapter. One thing about JDBC, JDBC doesn't really stand for anything. It's just a bunch of letters that Sun had trademarked, but you can think of it as ODBC for Java.

So in your connection dictionary, the important thing is to set a JDBC URL. That's determined by your database vendor or the particular JDBC driver you're using. You need to know the details of that, and that can be a little bit complicated. We have two examples here of Oracle and OpenBase. If you're using some other driver, figure out from the documentation how you want to address that.

Our plugin is our way of adding special behavior that works for that particular datasource. By default, we'll guess it by looking at the subprotocol in your JDBC URL. And you can programmatically decide to use certain plugins for a subprotocol name. So you have some control of that in your application. The driver, again, we'll try to guess that.

If you're using Oracle, we'll guess the right plugin. The plugin will guess which driver to try to load. You have to make sure that driver is available at runtime, and the easiest place to do that is to put it into your Java VM's X directory. So on Mac OS X, that would be in library/java/home/lib/x. This is documented on different platforms where you can put these things. You can put it in your class path anywhere. Just make it available at runtime.

We can experiment with models and if we don't have time for all the questions here, I'll be in the lab after this talk. So the other talks that are coming up today, DirectWeb's right after this, the Advanced Enterprise Objects Framework is a really good talk if you want to get more into advanced topics in EUF.