Lightweight R/O Mappingby Norbert Ehreke
An unwritten consensus in the IT industry is that data shared between object-oriented software and relational databases is best exchanged with object/relational (O/R) mapping frameworks where the entity relationship (ER) model follows the object-oriented model. This article proposes a reversed, lightweight approach supported by a small framework called Amber. This approach uses Java annotations to manage the CRUD cycle (Create Read Update Delete) of JavaBeans. Transaction management is put back into the database, and XML mapping descriptors are replaced by annotations. This article is for intermediate Java developers who are interested in efficient transactions with databases without XML descriptors.
Common O/R mapping frameworks are very powerful; however, their design and setup introduces several problems that are rarely discussed. We will address these shortcomings, listed below, demonstrated with a small framework called Amber.
- OO-driven data modeling leads to poor entity relationship models.
- XML descriptors make maintenance difficult.
- Transaction management in the O/R tier is difficult.
- The learning curve of existing frameworks is relatively steep.
For exchanging data between models that are described with entity relationships compared to object-oriented models, it necessary to overcome the so-called impedance mismatch. With most O/R mapping tools, the object model rules over the relational model. In essence, this means that the Java persistence layer is responsible for generating the entity relationship model from an existing object model. The idea is compelling, because the promise is that once the business model is designed, the development team no longer needs to worry about the persistence anymore.
For regular O/R tools, the ER model is a result, a product, at best a container. This clashes with system setups where the business process is actually designed as an ER model. In that case, then, a tuning of the ER model is difficult or even impossible because the O/R framework might reconstruct the ER model at any time. Also, when the business process changes and when the adaptations in the O/R domain are automatically reconstructed in the ER domain, the ER model becomes convoluted and sometimes the performance drops to critical levels.
Another problem exists. The classes that are to be persisted need to be configured with external XML specification (mapping) files. At first glance this seems to be not so bad. But when we're dealing with living systems, this becomes a pain in the neck very quickly. Whenever a change occurs, there is more than just one place to look in order to fix the problem, namely the source code and the mapping files.
Finally, existing O/R frameworks are designed to handle transactions. Following the philosophy of those frameworks, this is absolutely necessary because the storage container (i.e., the relational database) is just that: a stupid container. Having to deal with transaction management, however, is simply not desirable. This is something that belongs in the database.
Introducing AmberAmber approaches the problem of data exchange from the opposite angle. It assumes that the ER model is the reference for resulting OO structures. It also assumes that the database access is handled mainly via stored procedures, which provide a unified point of access to the database and which are also perfectly set up to handle transactions. Put into a provocative statement: the middle tier is implemented as a set of stored procedures. This means an expert on ER modelling, the DBA, is responsible for design and optimization, including stored procedures, which results in much better structures, and faster and more secure access, compared to automatically created ones. Therefore, a number of rather difficult problems that normally need to be addressed fall away.
- Transactions can (and should) be encapsulated within stored procedures.
- Read access deals only with result sets.
- Write access only requires a stored procedure call, not embedded SQL in Java code.
- With stored procedures, there are no security leaks via SQL injection.
Of course, this means that an entire playing field, which is normally located in the Java domain, is taken away. Make no mistake. That is a huge gain for Java developers, not a loss.
Central to Amber is the idea that no matter how a query is submitted to a database, the resulting tabular data is, in essence, a list of Java objects. Rather, that is the way it should be treated from the perspective of the Java developer. The only problem is to map the columns to the properties of an object. Conversely, when writing to a database, the properties of a Java object need to be mapped to the parameters in the call.
Amber maps the rows of a result set to a JavaBean and uses the same mechanism to map the bean, rather the contents of the bean, back to the parameters of an update, insert, or delete call to the database. For more information about JavaBeans and their definition, please check the Resources section.
This is done using a new Java language feature called annotations, available since J2SE 5.0.
Annotations, also called "metadata" under JSR 175, are supplementary code parts that can provide more information about the aim of a method, class, or field. The motivation for metadata stems mainly from the Javadoc API, which is used for inline documentation. So, without interfering with the actual code, annotations are used to describe the context of code, how it can or should be used. If you like to know more about annotations and what can be done with them, see Tiger: A Developer's Notebook, or, for a more playful example, my article " Annotations to the Rescue."