4.1. Persistence Options
You should acknowledge one simple fact up front: if you deal with a relational database, all roads in one form or another lead to JDBC. Whether you write the code yourself or let an ORM write it for you, SQL INSERTs, UPDATEs, and DELETEs are the lingua franca of any database-driven application.
While Sun maintains that JDBC is not an acronym, it looks suspiciously like "Java DataBase Connectivity" to many seasoned programmers. It is the API that allows us to load up database Drivers, make Connections, and create Statements that yield ResultSets upon execution.
While nothing is intrinsically wrong with ResultSets, OO purists bristle at the thought of dealing with a semi-structured collection of strings and primitives. Java programmers are taught from a tender young age that JavaBeans and DTOs are the one true way to represent business objects. So to get from ResultSets to DTOs, we must use hand-code methods that do the transformation for us, one car.setName(resultSet.getString("name")) at a time.
While this isn't terribly difficult, it does get tedious as the number of business objects and database tables grow. Maintaining two separate data schemas, one in Java and the other in SQL, strikes many as a flagrant violation of the DRY principle. The phrase "impedance mismatch" often comes up in JDBC discussions.
One potential way to avoid the problem of marshalling and unmarshalling JavaBeans is to remove the root causewhy not just create a database that deals natively with objects? On paper, object-oriented databases (OODBMS) seem to be the ideal solution to this problem. Sadly, OODBMSes have never gained any serious market share.
If you can't change the root data sourceand relational databases are deeply entrenched in most long-term persistence strategiesyour only other option is to come up with an API that manages the impedance mismatch: something that allows you to deal with native JavaBeans, and not only hides the JDBC complexity from you, but ideally entirely creates and manages the infrastructure.
One of the earliest attempts at this was the now infamous Entity Bean offering in the EJB specification. Entity beans came in two basic variations: Bean-Managed Persistence (BMPs) and Container-Managed Persistence (CMPs).
BMPs were really nothing more that a fancy way of saying, "I'm going to keep on doing the JDBC wrangling that I've already been doing." Since the Bean was responsible for its own persistence implementation, many programmers fell back on what they knew bestcar.setName(resultSet.getString("name")).
CMPs were closer to what we were hoping to achieve"let me define the business object and then have the container worry about how to persist it." The problem with CMPs ended up being twofold:
While Entity Beans still exist in the EJB specification today, they have largely fallen out of favor in the developer community.
Sun's next attempt at a JavaBean-centric persistence API was Java Data Objects(JDO). The 1.0 specification has been out for several years, but it hasn't captured a lot of mindshare. Some point to a differently but equally complicated API as its main problem. Traditional RDBMS vendors have been slow to support it, although OODBMS vendors have enthusiastically touted it as the Next Big Thing. Regardless, JDO is not an official part of the J2EE specification, so it has gone largely unnoticed by the server-side crowd.
Which leads us to the wild west of independent ORMs. Many solutionsboth commercial and open sourcehave popped up in the absence of an official specification from Sun. All allow you to traffic in unencumbered POJOsyou don't have to inherit from a specific object or implement a specific interface. Some use runtime reflection, and others rely on post-compilation bytecode manipulation to achieve their unobtrusive persistence goals.
JBoss Hibernate is one of the most popular of the bunch, although there are at least half a dozen viable candidates in this category. After we outline a JDBC strategy in this chapter, we'll walk through a simple Hibernate refactoring in the next chapter.
The existence of so many competing persistence solutions demonstrates that this is a complex problem with no one right answer. Any solution you pick will certainly outshine the others in certain circumstances and leave you wanting in others.
Apart from the obvious JBoss tie-in, there is one compelling reason why we chose Hibernate as our second persistence strategy, over any of the others we mentioned. Quite simply, it seems to best represent what next generation persistence APIs will look like.
In 2005, Sun announced the merger of the EJB 3.0 and JDO 2.0 specification teams. Both were working towardyou guessed itJavaBean-centric persistence APIs. Sun also invited the lead architects from the Hibernate project to sit on the team. Whatever the final name of the specification turns out to be, one thing is certainit will look and feel like Hibernate or any of the many other ORMs on the market today. By investing a little time in learning an ORM today, you will be that much closer to understanding the official Sun specification when it is released in the future.
But before you can really appreciate what an ORM brings to the table, let's look at a how to solve the persistence problem using nothing but JDBC.