Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

L09 The Behavioral Problem


Published on

The Data Source Layer patterns introduced in lecture L08 are structural patterns. They deal with moving data to and from the database. They try to solve the impedance mismatch problem. However, they do not have any logic as to when and under what circumstances data should be loaded to from the database and when written. Clearly accessing the database is slow, and doing so needlessly hurts performance.

In this lecture we look at the behavioural problem. How to solve issues like writing only changed record back into the database, loading only the needed data once, and how to load the data model partially.

We introduce three new design patterns: Unit of Work, Identity Map and Lazy Load.

Vist the course home page:

Published in: Technology
  • Be the first to comment

L09 The Behavioral Problem

  1. 1. Lecture 09 The Behavioral Problem
  2. 2. Reading  Fowler 3 Mapping to Relational Database – The Behavioural Problem  Fowler 12: Object-Relational Behavioral Patterns – Unit of work – Identity Map – Lazy Load
  3. 3. Agenda  Error handling  The Behavioral Problem  Object-Relational Behavioral Patterns – Unit of work – Identity Map – Lazy Load  Object-Relational Mapping
  4. 4. Error Handling Copyright © 2008 Ólafur Andri Ragnarsson
  5. 5. Error handling  Important aspect of programming – Programming the best case is usually easy – Making programs robust is another thing  Empty catch-blocks are usually not acceptable – Can be worse since the error gets lost – system.out.println is usually not practical  How to handle exception – Log the exception – Create a new exception and throw – Ignore and have upper layers handle the exception
  6. 6. Some guidelines  If you cannot handle an exception, don’t catch it  If you catch an exception, don’t eat it  If you need to handle an exception – Log with useful information – Catch it where you can do something with it  Use domain specific exception – Removes dependences – Example: Should SQLException be handled in the web layer if there is duplicate row in the database?
  7. 7. Exception Handling  Exceptions flow through layers – Catch exception at the source and throw a domain specific exception – Upper layers will handle the error  Example: Add User – Table Data Gateway add method catches a duplicate database exception – Throw domain specific exception – Each layer will ignore the exception, just pass it through – Web layer decides to display message to user saying the username chosen is already taken
  8. 8. Error Flow
  9. 9. Types of Exceptions  Unchecked – Can occur at any time – For example • OutOfMemoryError, NullPointerException  Checked – Part of declaration, must he handled or specifically handed to the caller public static String readFirstLine(String filename) throwsIOException { ...
  10. 10. Unexpected Exceptions  Problem with checked exceptions – – – – Too much code – unnessary try-catch blocks Hard-to-read code – difficult to see the real code The real error can get lost Dependencies  Guidelines – Use checked exception if caller must deal with the problem, the exception has direct consequences to the computation – In layered systems, if the calling layer will not be able to do anything, log and throw unchecked exception – Layer controlling the flow will handle
  11. 11. Unchecked exceptions
  12. 12. Example public class UserInserter extends SqlUpdate { ... public int insert(User user) { int rows = 0; try { rows = update(new Object[] { user.getUsername(), user.getName(), user.getEmail(), user.getPassword(), }); } catch (DataIntegrityViolationException divex) { String msg = "User '" + user.getUsername() + "' is already registered.";; throw new RuDuplicateDataException(msg, divex); }
  13. 13. Example catch (Throwable t) { String msg = "Unable to access Database: cause: " + t.getMessage(); log.severe(msg); throw new RuDataAccessException(msg, t); } return rows; } }
  14. 14. UserDataGateway  Do not need to handle the exception public class UserData extends RuData implements UserDataGateway { UserInserteruserInserter = ... public void addUser(User user) { userInserter.insert(user); } ... } public interface UserDataGateway extends RuDataGateway { User findUser(int id); Collection findByName(String name); void addUser(User user); void updateUser(User user); void deteleUser(int id); }
  15. 15. QUIZ Which of these statements is not true A) B) ✔ C) D) Checked exceptions must be always be handled by caller In layered systems, each layer must handle exceptions Unchecked exceptions are never handled Checked exceptions require more coding
  16. 16. The Behavioral Problem
  17. 17. The Behavioral Problem  Object-Relational Mapping – How you relate tables to objects  The Data Source Layer patterns are architectural patterns – the focus on structure – – – – Row Data Gateway, Table Data Gateway, Active Record, and Data Mapper  They simply tell you how to load and save objects to tables – What if you maintain these objects in-memory?
  18. 18. The Behavioral Problem  How to get various object to load and save themselves to the database – With objects in memory, how can we keep track of modified objects? – What if we have two of the same object in memory and both are changed? – How can we maintain consistency and data integrity? – What if you need object that is already in memory?
  19. 19. Keeping track of changed Objects  Simple way is to have an object that keeps track of other objects – Unit of Work  The idea is this – When object is loaded it is registered as “clean” in the UoW – If modified, it is marked “dirty” – When writing all objects back, just write the dirty ones
  20. 20. Keeping track of loaded Objects  What if you need an object from the database – is it already loaded? And changed? – Identity Map  The idea is this – Keep all objects in a map and check get them from the map – If they are not in the map, load them from the database
  21. 21. Loading Objects  For rich data models, what about loading object hierarchies? – Do we need to load all linked objects? – Lazy Load  The idea is this – We load part of the objects but maintain a placeholder that we use when the rest of the object is needed
  22. 22. Unit of Work Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems  Keeps track of objects that are moved in and out of the database – What has changed?
  23. 23. Unit of Work  How It Works – Unit of Work is an object that tracks all changes to the database – As soon as something affects the database, tell the Unit of Work – The Unit of Work must know the state of objects • Upon committing the Unit of Work decides what to do • Application programmers don’t have know what to write to the database  Two methods – Caller registration – Object registration
  24. 24. Unit of Work  Caller Registration – User of the object has to remember to register the object with the Unit of Work for changes
  25. 25. Unit of Work  Object Registration – The object must register itself with the Unit of work
  26. 26. Unit of Work  When to Use It – When you have in-memory objects you need to synchronize with the database – When you have many updates to objects and you want to avoid unneeded calls to the database to save the object  Benefits – Keeps the state of object in one place
  27. 27. Identity Map Ensures that each object gets loaded only once by keeping every loaded object in a map. Looks up objects using the map when referring to them  Keeps a record of all the objects that have been read
  28. 28. Identity Map  How It Works – Contains a map of all loaded objects – Provides method to get the objects  Choice of Key – Usually the primary key  Explicit or Generic – Explicit Identity Maps have method of the type of the object • Person findPerson (1) – Generic Identity Maps have generic objects and keys • Object find(“person”, 1)
  29. 29. Identity Map  How Many – One map per class or per session – Session maps works for database-unique keys – For multiple maps, maintain one per class or per table  Where to put them – Identity maps need to be somewhere – Can be part of Unit of work – Can be in a Registry  Identity Maps can be used as cache – Works well if objects are read-only
  30. 30. Identity Map  When to Use It – When you need to load objects to memory and you don’t want them duplicated – Main benefit of Identity Map is avoiding problems when object is updated in-memory – For immutable object, such as value object, Identity Map is not needed – object may be duplicated  Performance – When you need caching of objects for performance
  31. 31. Lazy Load An object that doesn’t contain all of the data you need but knows how to get it  Load only the data that is needed – Load the rest when it is needed
  32. 32. Lazy Load  How It Works – Object can contain other objects and associations – Loading all the data might be too much – Lazy Load delays loading until the objects are needed  Four ways to implement Lazy Load – – – – Lazy Initialization Virtual Proxy Value Holder A ghost
  33. 33. Lazy Load  Lazy Initialization – Uses a special marker value (usually null) to indicate a field isn't loaded – Every access to the field checks the field for the marker value and if unloaded, loads it Class Supplier... public List getProducts() { if (products == null) products = Product.findSupplier(getId()); return products; }
  34. 34. Lazy Load  Virtual Proxy – An object with the same interface as the real object – The first time one of its methods are called it loads the real the object and then delegates. Class VirtualList... private List source; private VirtualListLoader loader; public VirtualList(VirtualListLoader loader) { this.loader = loader; } private List getSource() { if(source == null) source = loader.load(); return source(); } public int size() { return getSource().size(); }
  35. 35. Lazy Load  Value Holder – An object with a getValue method – Clients call getValue to get the real object, the first call triggers the load Class SupplierVH... private ValueHolder products; public List getProducts() { return (List)products.getValue(); } Class ValueHolder… private Object Value; ... public Object getValue() { if (value==null) value = loader.load(); return value; }
  36. 36. Lazy Load  A ghost – The real object without any data – The first time you call a method the ghost loads the full data into its fields class Domain Object protected void Load() { if(IsGhost()) DataSource.load(this); } Class Employee... public String Name { get { Load(); return _name; } set { Load(); _name = value; } } String _name;
  37. 37. Lazy Load  When to Use It – When you have complex objects with associations with other objects – Need to decide how much to get on a hit and how many hits we want – Rule might be to bring in everything you need in one call • The overhead of taking extra fields in the table is not that high – The best time to use Lazy Load is when it involves an extra call and the data you’re calling isn’t used when the main object is used
  38. 38. QUIZ We are writing a business application which is using fairly large data set. We only need to update few objects. Writing them all back to database is too expensive. What pattern can we use? A) B) ✔ C) D) Lazy Load Identity Map Unit of Work Data Mapper
  39. 39. Object Relational Mapping
  40. 40. Object Relational Mapping (ORM)  Use a mapping layer to map between objects and tables – Mapping a data representation from an object model to a relational data model with a SQL-based schema  Mapping requires metadata – XML  Authoring and maintaining metadata is less work than maintaining SQL
  41. 41. Advantages of ORM  Can radically reduce the amount of code you need to write – 30% compared to JDBC for server side application  More Productivity  Applications are easier to maintain  Fosters thinking about an OO domain model
  42. 42. Disadvantages of ORM  Some loss of control over the persistence process  May be more difficult to tune queries  Performance characteristics of the tool may affect your application’s performance
  43. 43. When to use ORM?  Well-suited to ORM – Read-modify-write lifecycle – Little requirement for stored procedures  Poorly suited to ORM – “Window on data” application – Significant use of stored procedures – Write centric apps, where data is seldom read
  44. 44. When to use ORM?  Typical server-side applications are fairly well suited for ORM – 90%-95% of applications – But there are always some special cases – Mix and match as needed
  45. 45. Hibernate
  46. 46. Hibernate  Object/relational mapping tool – A persistence service that stores Java objects in relational databases – Provides an object oriented view of existing relational data  Uses reflection and XML mapping files to persist POJOs – No changes to business domain objects – The goal is to relieve the developer from a significant amount of common data persistence-related programming tasks
  47. 47. Architecture  High-level architecture Properties file define data access Mapping definition maps classes to tables
  48. 48. Architecture
  49. 49. Database Properties  File – hibernate.connection.username=andri hibernate.connection.password=abc123 hibernate.connection.url=jdbc:jtds:sqlserver:// hibernate.connection.driver_class=net.sourceforge.jtds.jdbc.Driver  Contains information to access the database – Username and password – URL – Database driver  Hibernate will automatically read the file from the classpath
  50. 50. Mapping File  File – hibernate-mapping – In the same package as Nemandi class <hibernate-mapping> <class name="" table="NEMENDUR"> <id name="kennitala" column="kennitala" type="string"> </id> <property name="nafn" column="nafn" type="string" length="64" not-null="false"/> <property name="netfang" column="netfang" type="string" length="64" not-null="false"/> <property name="hopur" column="hopur" type="string" length="32" not-null="false" /> </class> </hibernate-mapping>
  51. 51. Using Hibernate  Usually an application will – Create a single Configuration – Build a single instance of SessionFactory – Then instantiate Session objects Configuration cfg = new Configuration(); cfg.addClass(theClass); SessionFactory factory = cfg.buildSessionFactory(); Session session = factory.openSession();
  52. 52. Using Hibernate  Configuration – Allows the application to specify properties and mapping documents to be used when creating a SessionFactor  SessionFactory – Factory class to create Session objects  Session – Interface that represents a transaction – The main function is to offer create, read and delete operations for instances of mapped entity classes
  53. 53. Example  NemandiGateway public interface NemandiGateway { public Nemandi findNemandi(String kennitala); public Collection getNemendur(); public void addNemandi(Nemandi nemandi); }
  54. 54. Example  NemandiData – Constructor creates the configuration and the factory – Variable factory is used when a Session is needed public class NemandiData implements NemandiGateway { SessionFactory factory = null; public NemandiData() { Configuration cfg = new Configuration(); cfg.addClass(Nemandi.class); factory = cfg.buildSessionFactory(); }
  55. 55. Example  NemandiData – findNemandi public Nemandi findNemandi(String kennitala) { Session session = factory.openSession(); Nemandi nem = (Nemandi)session.get(Nemandi.class, kennitala); session.close(); return nem; }
  56. 56. Example  NemandiData – getNemendur public Collection getNemendur() { Session session = factory.openSession(); List l = session.createQuery( "SELECT n FROM AS n").list(); session.close(); return l; } – Uses the Hibernate Query Language, HQL
  57. 57. Example  NemandiData – addNemandi public void addNemandi(Nemandi nemandi) { Session session = factory.openSession(); Transaction tx = session.beginTransaction();; tx.commit(); session.close(); }
  58. 58. Summary  The Behavioral Problem – When objects are used  Object-Relational Behavioral Patterns – Unit of work – Identity Map – Lazy Load  Object-Relational Mapping