Kiss My App

Thursday, January 06, 2005

Dual Persistence Strategies

I was once asked if it's appropriate to use EJBs when fetching large datasets. The answer is of course no. To highlight this point, Sun has recently posted comparisons on persistence frameworks.

After writing my blog entry on Corporate Development, I realized that I wasn't covering all my bases with persistence. In the blog, I wrote about using open frameworks like JDO or Hibernate and throwing DAO's completely out the window. This isn't necessarily the impression I wanted to leave casual readers with.

For example, say you are writing an ordering application and you have various requirements having to do with line items, listing products, validating orders, etc. Idealy this sample of requirements would require two persistence strategies, one for supporting the view (large fetch/search operations) and one for supporting transactions (more robust data objects) (notice I'm beating this mule about objects never being able to serve all contexts).

Let's walk through the process of searching for a product and adding it to an order. Often times now the solution developers write is a DAO with a bunch of fetch operations for "light products" which contain data that only serves the view, then having a single fetch method by ID that returns a "full product". This dual object model returned from the DAO is done in order to optimize the frequent read operations required by the view. To implement our example above with DAO's:

Collection<ProductView> products;
products = productDao.findAllForCategoryId(catId);

// display view let them pick a product

String prodId = request.getParameter("prodId");
ProductData product = productDao.findById(prodId);

Now lets say we've written our DAO and encapsulated all read or view operations, later we want to be able to do sorting for all fetch operations. Now you have to go back and modify your DAO (which you've realized isn't very 'closed' for change). We also want to be able to search for products based on both category ID and price range, are you now going to add another method to the DAO? Hopefully you can see where I'm going here.

The solution that I should have clarified in my previous blog entry was to directly and openly use Hibernate or JDO for fetch operations that serve the view; a framework that allows us to freely modify or add behavior to an application without changing a DAO layer for every requirement or view feature.

You might enquire about testability since we are using direct DB calls for read operations, but in reality you want to be testing transactions (the competancies of your application) instead of validating that Hibernate or JDO actually sorted your products by name. Our DAO should be indifferent towards view requirements.

When it comes to serving the transactional persistence model, then yes, implement a DAO service that can be mocked and tested without a database. Your service DAO's now become much simpler because most all of their operations will only need to fetch DataObjects by id.

To conclude, I would go as far as creating view specific JSF components or JSP tags that allow you to query and sort object sets directly in the view using HQL. This doesn't seem too outlandish since databases aren't likely to change and you've already provided a layer of abstraction just by using Hibernate or JDO to produce an object model with mapped properties. Quite a few years ago, I created such a taglib for Apache OJB and I still got emails a few years later with people interested in using it for application development. Even in doing this, you are still preserving your transactional behavior and testability with DAO's in the application's domain model.

7 Comments:

Post a Comment

<< Home