Wiki source code of The EOModel

Version 26.1 by Pascal Robert on 2011/02/24 14:14

Show last authors
1 = The EOModel =
2
3 While it may seem obvious, data modeling is perhaps the most important phase of WebObjects application development. Data models form the foundation of your business logic and business logic forms the core of your application. Good business logic is essential to building effective applications, so it follows that good data models are essential to the success of the applications you build. Most importantly, data modeling plays a crucial role in object-relational mapping, the process in which database records are transposed into Java objects.
4
5 Using data models to develop data-driven applications provides you a unique advantage: applications are isolated from the idiosyncrasies of the data sources they access. This separation of an application's business logic from database logic allows you to change the database an application accesses without needing to change the application.
6
7 Also, WebObjects provides a rapid development environment that enables the creation of full-featured Web and desktop applications based on data models. So if you build well-designed data models, WebObjects gives you usable applications for free without any code.
8
9 Whenever possible, data modeling should occur in the earliest phases of application design and development. In data-driven applications, data modeling almost always influences an application's goals. That is, you cannot define an application's goals outside of the context of the application's data models.
10
11 Data models in Enterprise Objects reflect the earliest decisions about what data users see and how they are allowed to interact with data. This is because an important part of data modeling is deciding which entities and attributes are visible to clients and editable by clients. So by including data modeling as an early part of the design process, you can simplify future implementation details.
12
13 WebObjects provides you with a great tool for object-relational mapping called EOModeler. It allows you to
14 ■ build data models either from scratch or by analyzing preexisting data sources using reverse engineering
15 ■ add and customize entities (tables) and attributes (columns)
16 ■ form relationships between entities
17 ■ form relationships across multiple models
18 ■ generate SQL from a model to create or update a data-source schema based on the model
19 ■ generate Java classes from a model in which you can add custom business logic
20 ■ use stored procedures within data models
21 ■ graphically build fetch specifications for retrieving data
22 ■ flatten attributes and relationships
23 ■ define derived attributes
24 ■ build database queries in raw SQL
25
26 In an Entity-Relationship model, distinguishable things are known as entities, each entity is defined by its component attributes, and the affiliations, or relationships between entities, are identified (together, attributes and relationships are known as properties). From these three simple modeling objects—entities, attributes, and relationships—arbitrarily complex systems can be modeled.
27
28 == Entities ==
29
30 In a relational database data model, entities represent tables and an entity's attributes represent columns.
31
32 Each row in the table can be thought of as an instance of an entity. So, a customer record is called an instance of the Customer entity. Each instance of an entity typically maps to one object, but more complex mappings are possible.
33
34 Entities and attributes in data models derive their names based on the database elements they represent. A CUSTOMER table in a database, for example, would likely map to an entity named "Customer," though this is not strictly required. In your application, you refer to the CUSTOMER table not by its database name but by using its entity name, Customer.
35
36 === Entity characteristics ===
37
38 Class Name
39 The name of the class that corresponds to the entity. If you don't define a custom enterprise object class for an entity, the class name defaults to EOGenericRecord. You should use a fully qualified name but this isn't strictly required.
40
41 Client-Side Class Name
42 The name of the class that corresponds to the entity in the client side of a three-tier WebObjects Java Client application. If you don't define a client-side class, Enterprise Objects looks for a class in the client with the same name as the server-side enterprise object class. If no such class exists on the client, it uses EOGenericRecord. You should use a fully qualified name but this isn't strictly required.
43
44 External Query
45 Any valid SQL statement that you want executed when unqualified fetches are performed on the entity.
46
47 Name
48 The name your application uses for the entity. By default, EOModeler supplies a name based on the name of the corresponding table in the data source.
49
50 Open Entity
51 Adds a column with an icon which you can double-click to display an entity's attributes.
52
53 Parent
54 Specifies an entity's parent when using inheritance.
55
56 Qualifier
57 Specifies a restricting qualifier that is added to every fetch specification performed on the entity. Used when modeling inheritance hierarchies.
58
59 Read Only
60 Specifies if the entity is read-only.
61
62 Table
63 The name of the table in the data source that corresponds to the entity
64
65 === Advanced Entity Inspector ===
66
67 Batch Faulting Size lets you specify the number of faults that should be triggered when you first access an object of this type that is the destination of a to-many relationship. By providing a number in this field, you specify that number of faults of the same entity should be fetched from the data source along with the first fault. This improves performance by minimizing round trips to the data source.
68
69 External Query lets you specify any SQL statement to execute when Enterprise Objects performs an unqualified fetch on the entity. The columns selected by this SQL statement must be in alphabetical order by internal name and must match in number and type with the class properties specified for the entity.
70
71 Qualifier is used to specify a restricting qualifier. A restricting qualifier maps an entity to a subset of rows in a table. When you add a restricting qualifier to an entity, it invokes a fetch for that entity to retrieve objects only of the type specified by the restricting qualifier. See "Implementing Single-Table Mapping in a Model" (page 77) for more information on restricting qualifiers.
72
73 Parent is used to specify a parent entity for the current entity. This field is used to model inheritance. See "Modeling Inheritance" (page 67) for more details on this topic.
74
75 Read Only specifies whether the data that's represented by the entity can be altered by your application. This does not lock objects at the database level but rather works at a higher level (in the com.webobjects.eoaccess.EODatabaseContext object) so that if you try to save changes to data that's marked as read only, Enterprise Objects refuses the save and throws an exception.
76
77 Cache in Memory specifies that when one record in a table is fetched, the entire table is fetched into memory. Caching an entity's objects allows Enterprise Objects to evaluate queries in memory, thereby avoiding round trips to the data source. This is most useful for read-only entities where there is no danger of the cached data getting out of sync with the data in the data source.
78
79 Abstract lets you specify whether the entity is abstract. An abstract entity is one for which no objects are ever instantiated. For example, in the Real Estate database, the User entity is abstract and is never instantiated, whereas entities that inherit from it, such as Agent and Customer, are concrete classes that are instantiated. Like the Parent field, this option is used when modeling inheritance.
80
81 == Attributes ==
82
83 Contained within an entity is a list of attributes of the thing that's being modeled. The Customer entity could contain attributes such as a customer's first name, last name, phone number, and so on.
84
85 Entities can also have derived attributes, which do not directly correspond to any of the columns in the database table to which the entity maps. These attributes are usually computed from one or more attributes in the entity. For example, a derived attribute could represent the total amount of money spent by a customer by adding the amounts of all a customer's purchases together.
86
87 == Value Types ==
88
89 Value Type
90 When you choose a value class for a particular attribute, you sometimes do not provide Enterprise Objects with all the information the JDBC adaptor needs to negotiate with the data source.
91
92 For example, when you specify Number as the value class for a particular attribute, you are telling Enterprise Objects to use java.lang.Number, which is an abstract class. This is where the value type characteristic steps in. It specifies the exact class an attribute should map to.
93 The possible value types for numeric attributes are as follows(note case):
94
95 ■ b—java.lang.Byte
96 ■ s—java.lang.Short
97 ■ i—java.lang.Integer
98 ■ l—java.lang.Long
99 ■ f—java.lang.Float
100 ■ d—java.lang.Double
101 ■ B—java.math.BigDecimal
102 ■ c—java.lang.Boolean
103
104 == Prototypes ==
105
106 To make creating models easier, EOModeler supports prototype attributes. These are special attributes from which other attributes derive their settings. A prototype can specify any of the characteristics you normally define for an attribute. When you create an attribute, you can associate it with one of these prototypes, and the attribute's characteristics are then set from the prototype definition.
107
108 For example, you can create a prototype attribute called lastModified whose value class is Date, whose external type is datetime, and which corresponds to a column named LAST//MODIFIED. Then, when you create other entities, you can create an attribute and associate it with this prototype and the prototype's values are copied in to the new attribute. You can then change any values in or add values to the new attribute. Any value that is inherited from the prototype that you don't override uses the value defined in the prototype..//
109
110 Creating Prototype Attributes
111 The prototypes you can assign to attributes can come from two places:
112 ~1. An entity named EOAdaptorNamePrototypes, where AdaptorName is the name of the adaptor for your model. WebObjects 5.2 includes an adaptor for JDBC data sources and an adaptor for JNDI data sources. So you can create a prototype entity called either EOJDBCPrototypes or EOJNDIPrototypes, depending on the adaptor you use.
113 2. An entity named EOPrototypes.
114
115 To create a prototype attribute, first create a prototype entity—an entity named either EOAdaptorNamePrototypes or EOPrototypes—and add an attribute to it. Figure 3-3 shows an attribute in a prototype entity. It shows all the values that prototype attributes can define: column name, value class, external type, and value type.
116
117 To assign a prototype attribute to an attribute, reveal the Prototype column in table mode, and select a prototype attribute from the pop-up menu. The prototype attributes that appear in the pop-up list in the Prototype column include prototype attributes defined in any entity in any model in the application's model group, which includes the current model.
118
119 == Relationships ==
120
121 Every relationship has a cardinality. The cardinality defines how many destination records can potentially resolve the relationship. In relational database systems, there are generally two cardinalities:
122
123 ■ to-one relationship—for each source record, there is exactly one corresponding destination record
124 ■ to-many relationship—for each source record, there may be zero, one, or more corresponding destination
125 records
126
127 An employeeDepartment relationship is an example of a to-one relationship: An employee can be associated with only one department in a company. An Employee entity might also be associated with a Project entity. In this case, there would be a to-many relationship from Employee to Project called projects since an Employee can have many projects.
128
129 The construction of a relationship requires that you designate at least one attribute in each entity as a relationship key.
130
131 There are some general guidelines when choosing which attributes to use as relationship keys. In to-one relationships, the destination key must be a primary key in the destination entity. In to-many relationships, the destination key is usually a foreign key in the destination entity (which is most often a copy of the source entity's primary key). The source key or foreign key should emulate the destination key in that the data types must be the same and the names should be similar.
132
133 When you use relationship keys to express an affiliation between two entities, keep in mind these general rules:
134 ■ For to-one relationships, the source attribute is a foreign key in the source entity while the destination key is the primary key of the destination entity.
135 ■ For to-many relationships, the source attribute is the primary key in the source entity (but it can also be a foreign key in the source entity) while the destination key is a foreign key of the destination entity.
136
137 If you have consistency checking enabled in EOModeler, it warns you if any to-one relationships in your model have destination keys that are not primary keys.
138
139 If the data source on which your model is based includes foreign key definitions, these definitions are automatically expressed in your model when you create a model from an existing data source with the New Model Wizard. But if you are creating the schema within EOModeler, you need to define relationships in the model editor.
140
141 === To 1 Relations ===
142
143 === To Many Relations ===
144
145 === Many to Many Join Tables ===
146
147 === Flattened Relations ===
148
149 A flattened attribute is a special kind of attribute that you effectively add from one entity to another by traversing a relationship. When you form a to-one relationship between two entities (such as Person and PersonPhoto), you can add attributes from the destination table to the source table. For example, you can add a personPhoto attribute to the Person entity. This is called "flattening" an attribute and is equivalent to creating a joined column—it allows you to create objects that extend across tables.
150
151 Flattening attributes is just another way to conceptually "add" an attribute from one entity to another. A generally better approach is to traverse the object graph directly through relationships. Enterprise Objects makes this easy by supporting the notion of key paths.
152 The difference between flattening attributes and traversing the object graph (either programmatically or by using key paths) is that the values of flattened attributes are tied to the database rather than the object graph. If an enterprise object in the object graph changes, a flattened attribute can quickly get out of sync.
153
154 For example, suppose you flatten a departmentName attribute into an Employee object. If a user then changes an employee's department reference to a different department or changes the name of the department itself, the flattened attribute won't reflect the change until the changes in the object graph are committed to the database and the data is refetched (this is because flattened attributes are derived attributes—see "Definition (Derived Attributes)" (page 38) for more details). However, if you're using key paths in this scenario, users see changes to data as soon as they happen in the object graph. This ensures that your application's view of the data remains internally consistent.
155
156 Therefore, you should use flattened attributes only in the following cases:
157
158 ■ If you want to combine multiple tables joined by a one-to-one relationship to form a logical unit. For example, you might have employee data that's spread across multiple tables such as ADDRESS, BENEFITS, and so on. If you have no need to access these tables individually (that is, if you'd never need to create an Address object since the address data is always subsumed in the Employee object), then it makes sense to flatten attributes from those entities into the Employee entity.
159 ■ If your application is read-only.
160 ■ If you're using vertical inheritance mapping. See "Vertical Mapping" (page 69).
161
162 === Reflexive Relationships ===
163
164 A unique kind of relationship is the reflexive relationship—a relationship that shares the same source and destination entity. Reflexive relationships are important when modeling data in which an instance of an entity points to another instance of the same entity.
165
166 For example, to show who a given person reports to, you could create a separate manager entity. It would be easier, however, to just create a reflexive relationship. The managerID attribute is the relationship's source key whereas employeeID is the relationship's destination key. Where a person's managerID is the employeeID of another employee object, the first employee reports to the second. If an employee doesn't have a manager, the value for the managerID attribute is null in that employee's record.
167
168 Reflexive relationships can represent arbitrarily deep recursions. So, in the model above, a person can report to another person who reports to yet another person, and so on. This could go on until a person's managerID attribute is null, which denotes that person reports to no one.
169
170 === Owns Destination and Propagate Primary Key ===
171
172 The Owns Destination option lets you specify whether the relationship's source owns its destination objects. When a source object owns its destination object, for example, as when an Agent object owns its Customer objects, when a destination object (Customer) is removed from the relationship, it is also removed from the data source. Ownership implies that an owned object cannot exist without its owner.
173
174 The Propagate Primary Key option lets you specify that the primary key of the source entity should be propagated to newly inserted objects in the destination of the relationship. That is, when inserting objects that are the destination of the relationship, this option suppresses primary key generation for the destination entity and instead uses the source object's primary key as the primary key for the newly inserted destination object.
175
176 === Advanced ===
177
178 ==== Optionality ====
179
180 The Optionality section lets you specify whether a relationship is optional or mandatory. For example, you could require that all Document objects have a related Writer object but not require that all Document objects have a related Illustrator object. When you attempt to save an object that has a mandatory relationship that is not set (so the relationship is null), Enterprise Objects refuses the save and displays an error message stating that the object being saved has a mandatory relationship that must be set.
181
182 ==== Delete Rule ====
183
184 The options in the Delete Rule section specify what to do when the source object of a relationship is deleted. There are four options:
185 ■ Nullify disassociates all destination objects from the source object by removing references to them. So, when an Agent object is deleted, its related Customer objects are not deleted but the Customer objects' references to Agent are nullified (the entry in the join table is set to null).
186 ■ Cascade deletes all objects that are the destination of a relationship whose source is deleted. So, when an Agent object is deleted, all of its related Customer objects are also deleted.
187 ■ Deny refuses the deletion if a source object has any destination objects. So, if an Agent object has any Customer objects, deleting the Agent object is denied. In order for the deletion of the Agent object to succeed, its destination objects (Customer objects) must either be deleted or changed to something other than destination objects of the Agent object.
188 ■ No Action deletes the destination object but does not remove any back references to the source object. So, if a Customer object is deleted, its reference to its Agent object is not removed. Using this option may result in dangling references in the data source.
189
190 === Tips ===
191
192 The following tips are useful to keep in mind as you add relationships to your model:
193
194 The relationships you define in a model must reflect corresponding implementations in the data source, as well as the features supported by the adaptor your model uses. Enterprise Objects doesn't know, for example, if your adaptor supports left outer joins, so you need to be careful with regard to the characteristics you set for relationships.
195
196 Relationships can be compound, meaning that they can consist of multiple pairs of connected attributes. You can specify additional pairs of attributes only in the Relationship Inspector. Simply select a second source attribute and a second destination attribute and click Connect a second time.
197
198 A to-one relationship from one foreign key to a primary key must always have exactly one row in the destination entity—if this isn't guaranteed to be the case, use a to-many relationship. This rule doesn't apply to a foreign key to primary key relationship where a null value for the foreign key in the source row indicates that no row exists in the destination.
199
200 To-one relationships must join on the complete primary key of the destination entity.
201
202 == Using Multiple Models ==
203
204 === Relationships Across Models ===
205
206 The entities in one model can have relationships to the entities in another model. You can form such relationships even if the models map to different databases and different database servers.
207
208 When you add a model to a project, it becomes part of a model group. Every Enterprise Objects application includes a default model group, even if the project contains only one model. Each model you add to a project automatically becomes part of the project's model group. The only regulation between multiple models in a model group is that entity names must be unique.
209
210 == Fetch Specs in Model ==
211
212 You can set up an EOModel so that Enterprise Objects automatically invokes a stored procedure for these operations on an entity:
213
214 Insert to insert a new object into an entity
215 Delete to delete an object from an entity
216 Fetch All to fetch all objects in an entity
217 Fetch w/ PKto fetch the object in an entity with a particular primary key
218 Get PK to generate a new primary key for an entity
219
220 The stored procedures you enter in the Stored Procedure Inspector must correspond to a stored procedure in the model. If you created the model from an existing data source and chose the Ask About Stored Procedures option in the wizard, stored procedures are already added to the model. If this is not the case, however, you can add stored procedures to the model using the Add Stored Procedure command from the Property menu.
221
222 Finally, some stored procedures take arguments that you can also define in EOModeler. To do this, select a stored procedure in the tree view, which displays its arguments in the table. You can add arguments to a stored procedure by choosing Add Argument from the Property menu. Figure 5-7 shows arguments in a stored procedure.
223
224 In order for Enterprise Objects to automatically invoke a stored procedure for these operations, you must adhere to the requirements for each type of operation.
225
226 For each of the operations, if the stored procedure associated with an operation returns a value, Enterprise Objects ignores the return value.
227
228 For Fetch All operations, the stored procedure must not take any arguments and it should return a result set for all the objects in the corresponding entity. The rows in the result set must contain values for all the columns Enterprise Objects would fetch if it were not using the stored procedure, and it must return them in alphabetical order.
229
230 That is, the stored procedure should return values for primary keys, foreign keys used in class property joins, class properties, and attributes used for locking. These values must be returned in alphabetical order with regard to the attributes with which they are associated. For example, consider a Listing entity that has the attributes listingID, bedrooms, and sellingPrice. A stored procedure that fetches all the Listing objects should return the value for a listing's number of bedrooms, then its listingID, and then its selling price.
231
232 For Fetch w/ PK operations, the stored procedure must take an "in" argument for each of the entity's primary key attributes (most entities have a single primary key attribute). The argument names must match the names of the entity's primary key attributes. For example, a Listing entity has a single primary key attribute named listingID, so the stored procedures argument as defined in the model must also be listingID.
233
234 A Fetch w/ PK operation stored procedure should return a result set containing the row that matches the primary key passed in by the argument. The row must be in the same form as rows returned by the Fetch All operation.
235
236 For Insert operations, the stored procedure must take an "in" argument for each of the corresponding entity's attributes. The argument names must match the names of the corresponding EOAttribute objects.
237
238 For Delete operations, the stored procedure must take an "in" argument for each of the entity's primary key attributes. The argument names must match the names of the primary key attributes as in a Fetch w/ PK operation stored procedure.
239
240 For Get PK operations, the stored procedure must take an "out" argument for each of the entity's primary key attributes. The argument names must match the names of the primary key attributes as in a Fetch w/ PK operation stored procedure.
241
242 Insert, Delete, and Get PK operations should not return a result set.
243
244 == EO Inheritance ==
245
246 One of the issues that may arise in designing your enterprise objects—whether you're creating a schema from scratch or working with an existing database schema—is the modeling of inheritance relationships.
247
248 In object-oriented programming, it's natural to think of data in terms of inheritance. A Customer object, for example, naturally inherits certain characteristics from a Person object, such as name, address, and phone number. In inheritance hierarchies, the parent object or superclass is usually rather generic so that less generic subclasses of a related type can easily be added. So, in addition to the Customer object, a Client object also naturally derives from a Person object.
249
250 While this kind of thinking is inherent in object-oriented design, relational databases have no explicit support for inheritance. However, using Enterprise Objects, you can build data models that reflect object hierarchies. That is, you can design database tables to support inheritance by also designing enterprise objects that map to multiple tables or particular views of a database table.
251
252 Using inheritance adds another level of complexity to your data model, data source, and thus to your application. While it has its advantages, you should use it only if you really need to. This section provides information that will help you make that decision.
253
254 Suppose you're designing an application that includes Employee and Customer objects. Employees and customers share certain characteristics such as name and address, but they also have specialized characteristics. For example, an employee has a salary and a manager whereas a customer has account information and a sales contact.
255
256 Based on these data requirements, you might design a class hierarchy that has a Person superclass and Employee and Customer subclasses. As subclasses of Person, Employee and Customer inherit Person's attributes (name and address), but they also implement attributes and behaviors that are specific to their classes, as illustrated in Figure 7-1.
257
258 In object-oriented programming, when a subclass inherits from a superclass, the instantiation of the subclass implies that all the superclass' data is available for use by the subclass. When you instantiate objects of a subclass from database data, all the database tables that contain the data held in each class (whether subclass or superclass) must be accessed so that the data can be retrieved and put in the appropriate enterprise objects.
259
260 === Vertical Mapping ===
261
262 In this approach, each class is associated with a separate table. There is a Person table, an Employee table, and a Customer table. Each table contains only the attributes defined by that class.
263
264 This method of storage directly reflects the class hierarchy. If an object of the Employee class is retrieved, data for the Employee's Person attributes must be fetched along with Employee data. The relationship between Employee and Person is resolved through a join to give Employee access to its Person data. This is also the case for Customer. Vertical mapping requires a restricting qualifier if you want to fetch records from a parent entity (Person in this example).
265
266 ==== Advantages of Vertical Mapping ====
267
268 With vertical mapping, a subclass can be added at any time without modifying the Person table. Existing subclasses can also be modified without affecting the other classes in the inheritance hierarchy. The primary virtue of this approach is its clean, "normalized" design.
269
270 ==== Disadvantages of Vertical Mapping ====
271
272 Vertical mapping is the least efficient of all the approaches. Every layer of the class hierarchy requires a join table to resolve the relationships. For example, if you want to perform a deep fetch from Person, three fetches are performed: a fetch from Employee (with a join to Person), a fetch from Customer (with a join to Person), and a fetch from Person to retrieve all the Person attributes. If Person is an abstract superclass for which no objects are ever instantiated, the last fetch is not performed.
273
274 === Horizontal Mapping ===
275
276 In this approach, you have separate tables for Employee and Customer that each contain columns for Person. The Employee and Customer tables contain not only their own attributes, but all of the Person attributes as well. If instances of Person exist that are not classified as Employees or as Customers, a third table would be required. In other words, with horizontal mapping, every concrete class has a self-contained database table that includes all of the attributes necessary to instantiate objects of the class.
277
278 This mapping technique entails the same fetching pattern as vertical mapping except that no joins are performed. Horizontal mapping does not require restricting qualifiers.
279
280 ==== Advantages of Horizontal Mapping ====
281
282 Similar to vertical mapping, a subclass can be added at any time without modifying other tables. Existing subclasses can also be modified without affecting the other classes in the class hierarchy.
283
284 This approach works well for deep class hierarchies as long as the fetch occurs against the leaves of the class hierarchy (Employee and Customer) rather than against the root (Person). In the case of a deep fetch, horizontal mapping is more efficient than vertical mapping since no joins are performed. It's the most efficient mapping approach if you fetch instances of only one leaf subclass at a time.
285
286 ==== Disadvantages of Horizontal Mapping ====
287
288 Problems may occur when attributes need to be added to the Person superclass. The number of tables that need to be altered is equal to the number of subclasses—the more subclasses you have, the more effort is required to maintain the superclass.
289
290 If, for example, you need to add an attribute called middleName to the Person class, you then need to alter its subclasses, Employee and Customer. So if you have deep inheritance hierarchies or many subclasses, this can be tedious. However, if table maintenance happens far less often than fetches, this might be a viable approach for your application.
291
292 === Single-Table Mapping ===
293
294 With single-table mapping, you put all of the data in one table that contains all superclass and subclass attributes. Each row contains all of the columns for the superclass as well as for all of the subclasses. The attributes that don't apply for each object have null values. You fetch an Employee or Customer by using a query that returns just objects of the specified type (the table includes a type column to distinguish records of one type from the other).
295
296 Unlike vertical mapping, you don't need to flatten any of Person's attributes into Employee and Customer since these entities already have all of Person's attributes. Each subentity maps to the same table and contains attributes only for the properties that are relevant for that class.
297
298 When multiple entities are mapped to a single database table, you must set a restricting qualifier on each entity to distinguish its rows from the rows of other entities. A restricting qualifier maps an entity to a subset of rows in a table. This means that this qualifier is always used when fetches are performed on the entity, as well as any other qualifiers used during the fetch.
299
300 ==== Advantages of Single-Table Mapping ====
301
302 This approach is faster than the other two methods for deep fetches. Unlike vertical or horizontal mapping, you can retrieve superclass objects with a single fetch, without performing joins. Adding a subclass or modifying the superclass requires changes to just one table.
303
304 ==== Disadvantages of Single-Table Mapping ====
305
306 Single-table mapping results in tables that have columns for all of the attributes of each entity in the inheritance hierarchy. It also results in many null row values. While these aren't really disadvantages, they may conflict with some database design philosophies.
307
308
309 == EOGenerator ==
310
311 == Handling Blob Data ==
312
313 == Connection Dictionary ==
314
315 == Runtime Selection of the Connection Dictionary and Prototypes ==
316
317 == Debugging JDBC Connections and Jdbc2info ==