When looking at persistence solutions for objects the most common approach is O/R Mapping
(Object to Relational Mapping) and that is the approach that we have focused on.
In the early days of research we came across two inspirational papers. The first was Scott
Ambler's O/R Persistence Layer White Paper
that covers all the basics, and complementing that was Martin Folwer's Unit Of Work pattern.
At the time of development there were already commercial solutions like CocoBase and TopLink
that could do O/R Mapping and integrated with J2EE Containers for CMP. There were also a few
open source projects that could do varying degrees of O/R mapping, some that worked with
Containers, some that did not.
As we were intending to provide an open source framework that could work with, or without
a J2EE Container, we finally selected the Castor project with its JDO module (as a bonus
also comes with a pretty good XML marshalling capability too).
We developed a pluggable persistence engine based on Castor. This worked well, although we
had some teething issues with object relationships, and the lazy loading of them. Then with
the development of the Castor/JBoss plug-in that enables Castor to work within the JBoss
container as a database resource, we developed a second pluggable engine for persistence
within the container.
It was then possible to run the same persistence business code develop for stand alone
execution from within a session bean, just by flipping a framework property setting...Cool.
Of course for an application to be developed such that it can be run standalone or as a
J2EE application, it must be using our middleware layer (see later).
The above was a pretty good solution apart from some known issues with Castor JDO, and
mediocre performance and one major design assumption...
The design assumption we'd been making all along was that we were developing new domain
object models and using that to drive the relational data model. As with good modeling
practice all database tables had an OID (object id) key field, which was used for
inter-table relationships. This OID was an internally generated number. (Refer to the
White Paper as to why
this is all a great idea).
As this point in time we'd built a mini application on this basis and were pretty happy
with the results. But our next challenge may sound more familiar with what some of you
are facing out there...
We needed a solution that would allow our architecture to be used for web-enabling
existing application functionality. This 'existing application' comes with its already
designed relational data model, and as you can imagine the tables don't all have technical
keys, not all the relationships are modeled correctly, not everything is perfectly normalized.
It was clear to the group that the current Castor based engine was not a good fit for this.
We decided to take stock of the current architecture and see if it could be re-used. We have
a very good transaction manager, we know how Castor does its basic marshalling, we know that
we have a performance issue with relationships and lazy loading, we know that having a
flexible mapping between objects and tables is a good approach. And from that starting point
the 3rd Engine, the 'JDBCEngine' was born. The next step was to complement the
engine with tools to convert existing relational models into a set of domain objects
and mapping settings, so the that we could take an existing model and move it into our
framework in a matter of minutes. A huge time saver !! (See the Tools Section for
more details).
In the background of all this, there have been discussions on how to build the next
generation pluggable persistence engine that would allow the use of Entity Beans and CMP,
and still be transparent to the development of the domain objects and related business
functionality.
|