260 likes | 423 Views
Inheritance Mapping Patterns. Brett Daniel. Object/Relational : Apples/Oranges. Persistent storage is essential for many OO systems. Fundamental mismatch between object-oriented data model and relational data storage . Effect of Inheritance.
E N D
Inheritance Mapping Patterns Brett Daniel
Object/Relational : Apples/Oranges • Persistent storage is essential for many OO systems. • Fundamental mismatch between object-oriented data model and relational data storage
Effect of Inheritance • Inheritance makes O/R mapping especially difficult.
Inheritance Mappers “Each domain class [in an inheritance hierarchy] has a mapper that saves and loads the data for that domain class.” • Allows both concrete and abstract classes to handle their own O/R mapping • Domain objects loosely coupled to database
Alternatives • Transaction script • Just run queries • Use a relational domain model • Table Data Gateway • Row Data Gateway • Active Record • Table Module • Ad-hoc
Find() Behavior User calls find on concrete mapper object. find instantiates a new Executive and passes it and the database record to load. load fills in the Executive’s data then calls load on its superclass. After all loads return, find returns the filled object insert and update act similarly.
EmployeeMapper vs. AbstractEmployeeMapper • AbstractEmployeeMapper loads and saves data for the Employee class. • EmployeeMapper instantiates Employee objects. • Methods delegate to appropriate concrete mapper.
Aside: Generic Inheritance • Why find is not defined in the base class:“Common OO languages can’t let you change the declared return type of a method” • One can define find using generic inheritance • Forces concrete mappers to implement it • Other methods become type-safe • Hierarchy becomes more complex
Generic Inheritance Example public abstract class MapperBase<DomainObjectType, KeyType> { public void update(DomainObjectType domainObject) { /* ... */ } /* ... */ public abstract DomainObjectType find(KeyType key); /* ... */ } public abstract class AbstractEmployeeMapper<EmployeeType extends Employee> extends MapperBase<EmployeeType, Long> { /* ... */ } public static class HourlyEmployeeMapper extends AbstractEmployeeMapper<HourlyEmployee> { @Override public HourlyEmployee find(Long key) { // ... } }
Inheritance Mapping Schemes • Inheritance mapping determines how the mappers load and save domain objects • How is the inheritance hierarchy represented in the database? • Single Table Inheritance • Class Table Inheritance • Concrete Table Inheritance
Single Table Inheritance “Represents an inheritance hierarchy of classes as a single table that has columns for all the fields of the various classes.”
Single Table Inheritance • The type field refers to the type of Employee the record represents • Unused fields are left blank • Mapper retrieves record, checks type, instantiates appropriate object, and passes record to load
Single Table Inheritance • Advantages • Only one table • No joins when retrieving data • Fields can move up and down the hierarchy • Disadvantages • Not all fields are relevant for all classes • Wasted space • Large, confusing table • Possible field name conflicts
Class Table Inheritance “Represents an inheritance hierarchy of classes with one table for each class.”
Class Table Inheritance • Unique key options • One key per entity • Each table has own primary key, links to superclass table’s foreign key • Retrieval Options • “Leaf” mapper retrieves record containing all fields using join • Each mapper executes query on corresponding table
Class Table Inheritance • Advantages • Easy to understand • Very clear relationship between class and table • All columns used; high normalization • Disadvantages • Multiple tables requires join or multiple queries • Database changes required when fields move up and down hierarchy • Supertype table accessed very often • Must understand the class hierarchy to understand tables
Concrete Table Inheritance “Represents an inheritance hierarchy with one table per concrete class”
Concrete Table Inheritance • Can be thought of as a single record for each entity in the system • Primary keys must be unique across all tables • Cannot use auto_increment primary key • Cannot use database to enforce referential integrity • Retrieval • Concrete class retrieves record from corresponding table • Abstract class must query all tables to find where key exists
Concrete Table Inheritance • Advantages • Tables are independent • No unused fields within a table • No joins required • No single heavily-used table • Disadvantages • Difficult to ensure primary key uniqueness and referential integrity • Database does not contain anything corresponding to abstract classes • Field modifications require many changes to database • Abstract class mapper must query multiple tables to determine what concrete mapper to delegate to
Choosing a Mapping Scheme • Size (depth, width) of the hierarchy • Amount and type of expected changes • Whether the database is shared with other applications • Speed requirements • Type of RDBMS Schemes can be combined as needed
Soapbox • Personal choice: Class table inheritance with shared primary key and multiple queries • Mappers need only know their own table structure • No passing around data rows; only unique identifiers • Easy to modify: changes to a class prompt very obvious changes to mapper and table • No complex joins or name conflicts • Inheritance hierarchy enforced by database using table keys
Resources • Patterns of Enterprise Application Architecture. Martin Fowler 2003. Pages 278-304. • Mapping Objects to Relational Databases: O/R Mapping In Detail. http://www.agiledata.org/essays/mappingObjects.html • Solving the Data Access problem: to O/R map or not To O/R map http://weblogs.asp.net/fbouma/archive/2004/10/09/240225.aspx