Skip to main content

What do you do for your data access needs in your applications?

Posted by satyak on November 15, 2003 at 6:58 AM PST

What do you do for your data access needs in your applications?

This is the question I get asked a lot of times as I go through my new consulting opportunities every few years. My ideas on data acces have changed over the years. And they continue to evolve both by new insights from the field and also by the needs at hand. As a matter of fact, I am currently working on two ideas 1). Declarative Data Objects (DDO) and 2). Typed yet decalarative middle tier.

Before discussing those ideas in my future web logs, I want to give you an overview of what I do at the moment for my data access needs. Most of these architectural principles are designed into my jar file called aspire.jar. What follows is a summary of those data access strategies.

I would quite obliged if you were to add your few cents through the feedback section.

Aspire can be used as a data access library for Java programs. Aspire has three abstractions for data access.

  1. Relational abstraction
  2. hierarchical abstraction
  3. and Data Object abstraction.

In addition Aspire has a transactional aspect that cuts across all of data abstractions.This article examines each of these abstraction while identifying their relevance

Relational Abstraction

In Relational abstraction Aspire allows you to execute data reads from a variety of sources (primary being the relational database) and returns a collection of rows to the calling program. This abstraction is represented by the following java interfaces

  1. IDataCollection : Representing an idea of a collection of rows
  2. IDataRow: Representing a row
  3. IMetaData: Representing meta data
  4. IIterator: Representing a forward iteration of rows

You can learn how to use this abstraction in the following O'Reilly article available at
http://www.onjava.com/lpt/a/2856

This abstraction is suitable when you are writing business components that massages relational databases or exports contents out of databases. This may not be the API you want to use if you want to paint web pages. Turn to Hierarchical Data abstraction for this purpose.

Hiearchical Abstraction (Also called: HDS - Hierarchical Data Sets)

In this abstraction a single call to the data access API will return a Hierarchical Data Set (HDS). An HDS is a collection of nodes where each node in the tree represents relational data set. This abstraction is represented by a single java interface called:

Ihds: Representing "interface to hierarchical data set"

You can learn how to use this abstraction in the following O'Reilly article available at
http://www.onjava.com/lpt/a/3277

This abstraction is suitable when you are retrieving data to paint web pages. This is because the data needs of a web page are essentially hierarchical. Because of that this abstraction allows you retrieve all the data for a page in a single transaction. This abstraction is also suitable for B2B scenarios where you are returning a complex data set to the interested B2B parties.

When you are painting a web page you can get an "ihds" using this API and then you can use a JSP page to walk through the "ihds" to paint the individual sections of the page.

Data Object Abstraction

In this abstraction the focus is on typed data objects. Let us take the relational abstraction that was discussed above. The out put of a relational abstraction is a collection of rows where each row is represented as a generically typed IDataRow object. When you use typed language facilities like Java to access the columns, we can do a better job if this object is typed. For example if there is an IDataRow representing a row from a "Customer" table, it would be nice to see it as typed "CustomerRow" as opposed to the generic IDataRow. These typed objects have two advantages in a language environment:

  1. IDEs can prompt the programmer with the possible columns on that object
  2. Compile time checking when these columns are accessed

A minor disadvantage of this approach is that your solution will have lots of data objects whose sole purpose is to act as helpers for programmers and also potentially guard against column name mismatches which will otherwise show up as runtime errors.

Although not documented in any great detail, Aspire is primed for data object access in two ways. In the first mechanism, the "Iterator" that walks through the IDataCollection actually returns objects of type "object". This means that the collection producers can actually return typed objects as opposed to IDataRow. This facility is available even now. Send me an email if you are interested in using this facility.

The second approach to data objects is to use typed hierarchical data sets. In this approach using a hierarchical data sets an equivalent class definition is generated. The programmer will bind this class to the hierarchical data set on the client end. This is like placing a typed view window on the physical hierarchical data set. This approach has the nice advantage of a single row of physical data representing multiple data objects. The data objects will pull the values as needed. Again send me an email if you want to elaborate and pursue on this approach

Transactional Aspect

Irrespective of the data abstraction that is used, Aspire has an aspect that cuts across all of them orthogonally. This is the transactional aspect. Let me give you some examples of well known systems that display transactional aspects so that you can understand what I am talking about. Stored Procedures, Session Beans, CICS transactions are all examples that fall under this criteria.

In all these systems what you are doing is: You call a function identified by a name. That function will take a set of arguments. What comes back is a set of data. There is no state maintained across this transactional call. How this transaction is implemented is a different matter. But the usage of it is primarily functional and transactional.

So in Aspire irrespective of the data you want you end up calling a symbolic name (equivalent to a function) and passing in a hashtable of arguments. Aspire will locate a provider for that transaction (usually an object) and executes that transaction. Aspire uses configuration files to accomplish this.

Related Topics >>