Top Banner
Designing a Persistence Framework with Patterns
49

Persistence Framework

Jul 18, 2016

Download

Documents

ssss
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Persistence Framework

Designing a Persistence Framework

with Patterns

Page 2: Persistence Framework

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.

Page 3: Persistence Framework

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.

Page 4: Persistence Framework

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

– Caching: materialized objects are typically

cached for performance.

• Dematerialization (passivation):

– The reverse transformation.

Page 5: Persistence Framework

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.

Page 6: Persistence Framework

Key Ideas

• Mapping between a class and its persistent store and between object attributes and the fields in a record

• Object identity – to easily relate records to objects and ensure there are no inappropriate duplicates, records and objects have a unique identifier

• Database mapper – pure fabrication object responsible for materialization and dematerialization

6

Page 7: Persistence Framework

Key Ideas

• Caches – persistence services cache

materialized for performance

• Transaction state of object – State of

objects in relation to the current

transaction. Which objects are dirty?

• Transaction operations – Commit and

Rollback

7

Page 8: Persistence Framework

Key Ideas

• Lazy materialization – not all objects are

materialized at once; materialization on

demand

• Virtual proxies – Lazy materialization can

be implemented using a smart reference

known as a virtual proxy

8

Page 9: Persistence Framework

Mapping

Between a class and its persistent store

Between object attributes and fields in a record

Page 10: Persistence Framework

Mapping objects and tables

Manufacturer

name

city

...

...

name city

Now&Zen Mumbai

MANUFACTURER TABLE

: Manufacturer

name = Now&Zen

city = Mumbai

Celestial

ShorteningSan Ramon

Page 11: Persistence Framework

Object Identifier

Page 12: Persistence Framework

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.

Page 13: Persistence Framework

Fig. 37.3 OIDs link objects and records

OID

xyz123

abc345

This is a simplified design.

In reality, the OID may be

placed in a Proxy class.

primary key

Manufacturer

city

name

oid : OID

...

...

name city

Now&Zen Mumbai

MANUFACTURER TABLE

: Manufacturer

city = Mumbai

name = Now&Zen

oid = xyz123

Celestial

ShorteningSan Ramon

Page 14: Persistence Framework

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.

Page 15: Persistence Framework

Fig. 37.4 The Persistence Façade

1

PersistenceFacade

...

getInstance() : PersistenceFacade

get( OID, Class ) : Object

put( OID, Object )

...

: DBProductsAdapter1

: PersistenceFacade

pd = get(...)

// example use of the facade

OID oid = new OID("XYZ123");

ProductDescription pd = (ProductDescription) PersistenceFacade.getInstance().get( oid, ProductDescription.class );

Page 16: Persistence Framework

Database Mapper

Page 17: Persistence Framework

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.

Page 18: Persistence Framework

Fig. 37.5 Database Mappers

each mapper gets and puts objects in its own unique way,

depending on the kind of data store and format

1

PersistenceFacade

getInstance() : PersistenceFacade

get( OID, Class ) : Object

put( OID, Object )

...

ProductSpecification

RDBMapper

...

get( OID) : Object

put( OID, Object )

...

ProductSpecification

FlatFileMapper

...

get( OID) : Object

put( OID, Object )

...

Manufacturer

RDBMapper

...

get( OID) : Object

put( OID, Object )

...

note that the Class as a

parameter is no longer

needed in this version of

get, as the class is

"hardwired" for a particular

persistent type

1

«interface»

IMapper

get(OID) : Object

put( OID, Object )

...

Class

UML notation: This is a qualified assocation. It means:

1. There is a 1-M association from PersistenceFacade to IMapper objects.

2. With a key of type Class, an IMapper is found (e.g., via a HashMap lookup)

Page 19: Persistence Framework

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.

Page 20: Persistence Framework

Fig. 37.7 Template Method for mapper objects

Abstract

PersistenceMapper

+ get( OID) : Object {leaf}

# getObjectFromStorage(OID) : Object {abstract}

...

«interface»

IMapper

get(OID) : Object

put( OID, Object )

...

// template method

public final Object get( OID oid )

{

obj := cachedObjects.get(oid);

if (obj == null )

{

// hook method

obj = getObjectFromStorage( oid );

cachedObjects.put( oid, obj );

}

return obj;

} HOOK

TEMPLATE

Page 21: Persistence Framework

Fig. 37.8 Overriding the hook method

ProductDescription

RDBMapper

# getObjectFromStorage(OID) : Object

Abstract

PersistenceMapper

+ get( OID) : Object {leaf}

# getObjectFromStorage(OID) : Object {abstract}

...

// template method

public final Object get( OID oid )

{

obj := cachedObjects.get(oid);

if (obj == null )

{

// hook method

obj = getObjectFromStorage( oid );

cachedObjects.put( oid, obj )

}

return obj

}

// hook method override

protected Object getObjectFromStorage( OID oid )

{

String key = oid.toString();

dbRec = SQL execution result of:

"Select * from PROD_DESC where key =" + key

ProductDescription pd = new ProductDescription();

pd.setOID( oid );

pd.setPrice( dbRec.getColumn("PRICE") );

pd.setItemID( dbRec.getColumn("ITEM_ID") );

pd.setDescrip( dbRec.getColumn("DESC") );

return pd;

}

IMapper

Page 22: Persistence Framework

Fig. 37.9 Template Method twice to factor common code for RDB

Abstract

RDBMapper

tableName : String

+ «constructor» AbstractRDBMapper( tableName )

# getObjectFromStorage(OID) : Object {leaf}

# getObjectFromRecord(OID, DBRecord) : Object {abstract}

- getDBRecord(OID) : DBRecord

Abstract

PersistenceMapper

+ get( OID) : Object {leaf}

# getObjectFromStorage(OID) : Object {abstract}

...protected final Object

getObjectFromStorage( OID oid )

{

dbRec = getDBRecord( oid );

// hook method

return getObjectFromRecord( oid, dbRec );

}

IMapper

ProductDescription

RDBMapper

+ «constructor» ProductDescriptionRDBMapper(tabName)

# getObjectFromRecord(OID, DBRecord) : Object

// hook method override

protected Object

getObjectFromRecord( OID oid, DBRecord dbRec )

{

ProductDescription pd = new ProductDescription();

pd.setOID( oid );

pd.setPrice( dbRec.getColumn("PRICE") );

pd.setItemID( dbRec.getColumn("ITEM_ID") );

pd.setDescrip( dbRec.getColumn("DESC") );

return pd;

}

private DBRecord getDBRecord OID oid )

{

String key = oid.toString();

dbRec = SQL execution result of:

"Select * from "+ tableName + " where key =" + key

return dbRec;

}

Page 23: Persistence Framework

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.

Page 24: Persistence Framework

Fig. 37.10 The persistence framework

1

«interface»

IMapper

get(OID) : Object

put( OID, Object )

...

Class

1

+ PersistenceFacade

getInstance() : PersistenceFacade

get( OID, Class ) : Object

put( OID, Object )

...

Abstract

PersistenceMapper

+ get( OID) : Object {leaf}

# getObjectFromStorage(OID) : Object

...

Abstract

RDBMapper

+ AbstractRDBMapper(tableName)

# getObjectFromStorage(OID) : Object {leaf}

# getObjectFromRecord(OID, DBRecord) : Object

- getDBRecord(OID) : DBRecord

Persistence

NextGen Persistence

ProductDescription

RDBMapper

+ ProductDescriptionRDBMapper(tableName)

# getObjectFromRecord(OID, DBRecord) : Object

ProductDescription

FileWithXMLMapper

# getObjectFromStorage(OID) : Object

Sale

RDBMapper

...

# getObjectFromRecord(OID, DBRecord) : Object

ProductDescription

InMemoryTestDataMapper

# getObjectFromStorage(OID) : Object

Page 25: Persistence Framework

Cache

Page 26: Persistence Framework

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.

Page 27: Persistence Framework

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.

Page 28: Persistence Framework

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;

}

Page 29: Persistence Framework

Transaction state of Object

Page 30: Persistence Framework

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.

Page 31: Persistence Framework

Fig. 37.12 Statechart for PersistentObject

OldClean OldDirty

OldDelete

commit / delete

delete

New

[ from DB][new (not from DB)]

save

commit / update

delete

rollback / reload

rollback / reloadcommit / insert

State chart: PersistentObject

Legend:

New--newly created; not in DB

Old--retrieved from DB

Clean--unmodified

Dirty--modified

Deleted

Page 32: Persistence Framework

Fig. 37.13 Persistent object classes extend PersistentObject

PersistenceDomain

ProductDescription

...

PersistentObject

oid : OID

timeStamp:

DateTime

commit()

delete()

rollback()

save()

...

• PersistentObject provides common technical

services for persistence

Page 33: Persistence Framework

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.

Page 34: Persistence Framework

Fig. 37.14 Applying the State pattern

PersistentObject

oid : OID

state : PObjectState

commit()

delete()

rollback()

save()

setState(PObjectState)

...

PObjectState

commit(obj : PersistentObject)

delete(obj : PersistentObject)

rollback(obj : PersistentObject)

save(obj : PersistentObject)

OldDirty

State

commit(...)

delete(...)

rollback(...)

1

OldClean

State

delete(...)

save(...)

New

State

commit(...)

OldDelete

State

commit(...)

rollback(...)

Product

Specification

...

...

Sale

...

...

*

{ state.delete( this ) }

{

// default no-op

// bodies for

// each method

}

{ // delete

obj.setState( OldDeleteState.getInstance() ) }

{ // save

obj.setState( OldDirtyState.getInstance() ) }

{ // rollback

PersistenceFacade.getInstance().reload( obj )

obj.setState( OldCleanState.getInstance() ) }

{ // commit

PersistenceFacade.getInstance().update( obj )

obj.setState( OldCleanState.getInstance() ) }

{ state.rollback( this ) }{ state.commit( this ) }

{ state.save( this ) }

{ // commit

PersistenceFacade.getInstance().insert( obj )

obj.setState( OldCleanState.getInstance() ) }

{ // commit

PersistenceFacade.getInstance().delete( obj )

obj.setState( DeletedState.getInstance() ) }

Page 35: Persistence Framework

Transaction Operations

Page 36: Persistence Framework

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.

Page 37: Persistence Framework

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”.

Page 38: Persistence Framework

Fig. 37.15 Commands for database operations

«interface»

ICommand

execute( )

undo()

DBInsertCommand

execute()

DBUpdateCommand

execute()

DBDeleteCommand

execute()

Transaction

commands : List

commit()

addDelete(obj:PersistentObject)

addInsert( obj:PersistentObject)

addUpdate( obj:PersistentObject)

sort()

...

1..*

DBCommand

object : PersistentObject

execute() {abstract}

undo() {leaf}

undo is a no-op for

this example, but a

more complex

solution adds a

polymorphic undo

to each subclass

which uniquely

knows how to undo

an operation

PersistentObject

commit()

...1{

commands.add( new DBUpdateCommand(obj) );

}

use SortStrategy objects to allow

different sort algorithms to order the

Commands

perhaps simply

object.commit()

but each Command can

perform its own unique

actions

{

sort()

for each ICommand cmd

cmd.execute()

}

Page 39: Persistence Framework

Lazy Materialization with a Virtual

Proxy

Page 40: Persistence Framework

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.

Page 41: Persistence Framework

Fig. 37.16 Manufacturer Virtual Proxy

Manufacturer

Proxy

realSubject : IManufacturer

- getRealSubject() : IManufacturer

+ getAddress()

...

Manufacturer

address

getAddress()

...

«interface»

IManufacturer

getAddress()

...

Proxy-for 1

realSubject

{

return getRealSubject().getAddress()

}

ProductSpecification

manufacturer : IManufacturer

...

getManufacturerAddress() : Address

1

{

if ( realSubject == null )

realSubject = PersistenceFacade.get(oid, Manufacturer.class);

return realSubject;

}

PersistentObject

oid

...

1

{

return manufacturer.getAddress()

}

actually references an

instance of

ManufacturerProxy

1

23

Page 42: Persistence Framework

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.

Page 43: Persistence Framework

Architectural Analysis

Page 44: Persistence Framework

Architectural Analysis

• Focus on requirements that strongly

influence the architecture.

– e.g Secure system.

• Focus on Non-Functional requirements.

• Identify variation points(e.g third party

services) and evolution points(in future).

Page 45: Persistence Framework

Architectural Analysis

• Steps in Architectural Analysis.

– Identify and analyze the non-functional

requirements

– Analyze alternatives

• Remove requirement, Hire an expert etc

• Architectural design principles

– High cohesion

– Low coupling

– Protected variations

Page 46: Persistence Framework

Logical architecture refinement

Page 47: Persistence Framework

Logical architecture refinement

• Interlayer collaboration

(UI,DOMAIN,TECHNICAL SERVICE

layer)

• Apply façade, observer and controller

pattern.

Page 48: Persistence Framework

Package design

Page 49: Persistence Framework

Package design

• Organize packages to reduce the impact

of changes.

• Relational Cohesion(RC)

RC= pesNumberofty

ionernalrelatnumberof int

Low RC=>package contain unrelated thing