370 likes | 546 Views
Chapter 37. Designing a Persistence Framework with Patterns. Persistent Objects. Storage mechanisms: Object databases Relational databases Other – flat files, XML structures, hierarchical databases, etc. Object-Relational (O-R) mapping service: maps an object to a relational record.
E N D
Chapter 37 Designing a Persistence Framework with Patterns
Persistent Objects • Storage mechanisms: • Object databases • Relational databases • Other – flat files, XML structures, hierarchical databases, etc. • Object-Relational (O-R) mapping service: maps an object to a relational record.
Persistence Frameworks • Persistence framework: general-purpose, reusable, extendable set of types that provides functionality to support persistent objects. • Persistence service: subsystem created by persistence framework. • In technical services layer. • Called an O-R mapping service for RDB’s. • E.g., Hibernate for Java.
Materialization • Transforming a non-object representation of data from a persistent store into objects. • Lazy materialization: an instance is only materialized on demand, when needed. • Implemented by a Virtual Proxy (sect. 37.18). • Caching: materialized objects are typically cached for performance. • Dematerialization (passivation): • The reverse transformation.
Representing Objects as Tables • Pattern: define a table in an RDB for each persistent object class. • Primitive object attributes map to columns. • Attributes that refer to other complex objects is more complicated.
Object Identifier Pattern • Assign an object identifier (OID) to each record and object (or proxy of an object). • Relates records to objects. • Avoids duplicates. • Usually alphanumeric value. • In object-land, represented by an OID interface or class. • In RDB, usually a fixed-length char value. • Every table has an OID as primary key. • Maps every object to some row in some table.
Accessing a Persistence Service with a Façade • Façade provides a unified interface to a subsystem. • Operation to retrieve an object given OID. • Type of object to materialize is also needed. • Operation to store an object (dematerialize). • Façade delegates requests to subsystem objects.
Database Mapper Pattern • Direct mapping: persistent object class defines the code to save itself in a DB. • Strong coupling to persistent storage. • Reduced cohesion: technical services mixed with application logic. • Indirect mapping: create a class that is responsible for materialization, dematerialization and object caching. • Database Mapper or Database Broker. • Different mapper class for each persistent object class.
Template Method Pattern (GoF) • Define a method in a superclass that defines the skeleton of an algorithm, with its varying and unvarying parts. • Invokes other methods (“hook” methods), some of which may be overridden in a subclass to provide unique behavior at points of variability. • Template method is typically public, hook methods protected.
Fig. 37.9 Template Method twice to factor common code for RDB
Persistence Framework for NextGen POS • NextGen-specific classes are in a different package from general technical services Persistence package. • IMapper, AbstractPersistenceMapper, and AbstractRDBMapper are part of framework. • ProductDescriptionRDBMapper is a subclass added by application programmer. • ProductDescriptionInMemoryTestDataMapper produces hard-coded objects for testing without accessing an external DB.
Guarded Methods • AbstractPersistenceMapper.get method contains critical section. • The same object could be materializing concurrently on different threads. • Entire persistence subsystem may be distributed to a separate process on another computer. • PersistenceFacade as a remote server object. • Many threads running simultaneously, serving multiple clients.
Configuring Mappers with a Mapper Factory • A factory object MapperFactory can be used to configure the persistence façade with a set of IMapper objects. • Don’t name each mapper with a different operation, as in: class MapperFactory { public IMapper getProductDescriptionMapper() {…} public IMapper getSaleMapper() {…} } • Instead, return a collection of mappers: class MapperFactory { public Map getAllMappers() {…} }
Data-driven Mapper Instantiation • The façade can then initialize its collection of IMappers with: class PersistenceFacade { private java.util.Map mappers = MapperFactory.getInstance().getAllMappers(); } • The factory can read system properties or use the reflective capabilities of the language (e.g., Java) to discover which IMapper classes to instantiate.
Cache Management • Pattern: Make the Database Mappers responsible for maintaining a local cache of materialized objects to improve performance. • When objects are materialized, they are cached, with their OID as key. • Subsequent requests to the mapper for an object will be satisfied from the cache if the object has already been materialized.
A Class for SQL Statements • Consolidate all SQL operations in a Pure Fabrication singleton. • SQL operations: SELECT, INSERT, . . . • RDB mapper classes collaborate with SQL-statements class to obtain a DB record or ResultSet (Java). • This is preferable to hard-coding SQL statements into the different RDB mapper classes.
Example of a SQL-statements Class • Interface: class RDBOperations { public ResultSet getProductDescriptionData(OID oid){…} Public ResultSet getSaleData( OID oid ) { … } } • Mapper: class ProductDescriptionRDBMapper extends AbstractPersistenceMapper { protected Object getObjectFromStorage( OID oid ) { ResultSet rs = RDBOperations.getInstance(). getProductDescriptionData(oid); ProductDescription ps = new ProductDescription(); ps.setPrice( rs.getDouble( “PRICE” ) ); ps.setOID( oid ); return ps; }
Transactional States and the State Pattern • Assume: • Persistent objects can be inserted, deleted, or modified. • Modifying a persistent object does not cause an immediate DB update – an explicit commit operation must be performed. • The response of an operation depends on the transactional state of the object: • An “old dirty” object was modified after retrieval. • An “old clean” object need not be updated in DB. • Delete or save causes state change, not commit.
Fig. 37.13 Persistent object classes extend PersistentObject • PersistentObject provides common technical services for persistence
The State Pattern (GoF) • Problem: An object’s behavior is dependent on its state, and its methods contain case logic reflecting conditional state-dependent actions. • Solution: Create state classes for each state, implementing a common interface. Delegate state-depended operations from the context object to its current state obj. • Ensure the context object always points to a state object reflecting its current state.
Database Transactions • Transaction: a unit of work whose tasks must all complete successfully or none must be completed. • Completion is atomic. • Represent the set of tasks to be done with a Transaction class. • The order of database tasks within a transaction can affect its success and performance. • Ordering database tasks can help: generally, inserts first, then updates, then deletes.
The Command Pattern (GoF) • Problem: How to handle requests or tasks that need functions such as prioritizing, queueing, delaying, logging, or undoing. • Solution: Make each task a class that implements a common interface. • Actions become objects that can be sorted, logged, queued, etc. • Each has a polymorphic execute method. • E.g., command objects can be kept in a history stack to enable “undo”.
Lazy Materialization with a Virtual Proxy • Virtual Proxy (GoF): a proxy for another object (the real subject) that materializes the real subject when it is first referenced. • A lightweight object that stands for the real object that may or may not be materialized. • E.g., a Manufacturer object is rarely used, but a ProductDescription has attribute visibility to an IManufacturer instance. • When ProductDescription sends a getAddress message to the ManufacturerProxy, it materializes the real Manufacturer, using its OID.
Representing Relationships in Tables • Representing Object Relationships as Tables pattern: • One-to-one associations • Place an OID foreign key in one or both tables representing the objects in a relationship, or treat as a one-to-many association, as below. • One-to-many associations (a collection) or many-to-many associations: • Create an associative table that records the OIDs of each object in relationship.