DekGenius.com
Previous Section  < Day Day Up >  Next Section

7.4 Evaluating Hibernate

We've covered some of the Hibernate basics. To recap, it's a persistence framework that allows transparent persistence from Java beans to relational databases over JDBC. So how does Hibernate stack up against our five principles?

7.4.1 Keep It Simple

It's easy to build simple solutions if you're solving simple problems. Complicated problems like persistence demand more thought and effort. If you want to understand how complex persistence frameworks can be, check out EJB entity beans. Compare that model with Hibernate. Hibernate's model code is fully transparent (except for the need to provide a default, parameter-less constructor). Configuration is a breeze. The mappings are simple when you're solving simple problems.

It's not just the Hibernate framework that benefits from a simpler mindset; Hibernate applications also reap the benefits. It's also easy to get started. I've learned that most students of my classes are able to get going in an hour or so, which is about how long it takes to get your first JDBC application off of the ground. After using Hibernate for some commercial applications, I've learned that they are easy to write and easy for my customers to understand. But simplicity does not mean Hibernate is too basic to solve difficult problems.

7.4.2 Do One Thing, and Do It Well

When you attack a big problem, it's tempting to just solve some smaller problems around the perimeter of your domain. With persistence frameworks, many designers try to build in transaction management, security, distribution, or other aspects. It's far better to layer your code, focusing each loosely coupled layer on just one aspect of the problem.

It's tough to solve every aspect of a problem domain like persistence. In order to focus on a difficult problem, you have to make simplifying assumptions. Hibernate creators wisely made some basic assumptions that let them simplify their implementation:

  • Hibernate uses only JDBC. Some persistence frameworks support many types of data stores. By supporting only relational databases, Hibernate developers did not need to deal with nonrelational problems, thus simplifying their query language and focusing on JDBC.

  • While some persistence frameworks support all types of Java classes, Hibernate supports only Java beans. The developers were therefore able to make use of the existing reflection API. To be fair, for many problems, reflection may be too simple. Hibernate has added CGLib in order to do byte code enhancement to support lazy loading, which may be a better overall technique for transparency, in this case.

  • Hibernate punts on some of the peripheral problems, using other frameworks instead. Apache Commons handles logging, JTA provides a more robust transaction API, and JNDI provides a naming interface to help locate services.

By leaving these details to others, Hibernate creators were able to focus on building a fast, light persistence framework. Instead of wringing their hands over the performance of reflection, they wisely worked on creating efficient SQL first. That could only be done through loose coupling at the right places. As you'll see in Section 4.4, the Hibernate extensions are loosely coupled and pluggable in the right places.

7.4.3 Strive for Transparency

For the most part, the Java community has had to wait a long time for transparent persistence. For a while, most of our attention was diverted as we tried to make the EJB experiment work. For persistence frameworks, transparency affects productivity more than any other feature. If you haven't used transparent persistence before, one look at our application will show you why you should. You're simply free to deal with the business domain independently of any other application concerns. This ability lets you break your programming down into manageable pieces with clearly defined roles. It also makes your domain easier to write and understand.

7.4.4 Allow for Extension

Too often, simple solutions are dead ends. They cannot be extended in the appropriate places. When you build simple software, it's got to be able to grow. The only constant in software development is change. You must anticipate the places your users will need to extend your frameworks and applications. The most successful open source projects are those that allow for extension. Apache allowed plug-ins to process many different types of web content. Ant allowed developers to plug in custom tasks, so they could use Ant for highly customized builds. Eclipse is an application development environment that's gathering momentum because of the vast array of compatible extensions. Hibernate also allows for smart extension in a number of important places:


SQL dialects

Hibernate users can switch between databases by simply configuring a different dialect. Users of a given dialect can choose to use proprietary extensions for added performance, or instead use a more generic dialect. The interface to create a dialect is open, so you can create new dialects as you need them in order to support the databases you need for a project.


The JDBC connection

Much of the OOP community frowns on the use of stored procedures but in the real world, they are a fact of life. Hibernate users can access the JDBC connection directly in order to use features that are not supported by Hibernate, such as stored procedures. By providing direct access to the level of abstraction immediately below, the architects allowed extension to areas completely outside of their realm.


Configurable transaction API

JDBC developers often like to manage their own transactions, but many advanced J2EE developers need more. Hibernate conveniently passes transaction responsibility through to the database for simple applications with explicit transaction support, and also lets the user configure the more advanced transactions through JTA.

I'd like to point out that standards play a role here, too. While you don't need to support every open standard, you can get significant leverage from standards in likely areas of extension. For example, the Hibernate inventors understood that JTA makes sense for transactions that may have a scope beyond the basic persistence framework. On the other hand, it clearly did not make sense to support earlier releases of JDO, since that specification forced byte code enhancement and had an awkward query language that might complicate and possibly confuse the API.

7.4.5 You Are What You Eat

Hibernate does a good job of integrating core standards where they exist, but it rarely forces you to use a complex standard. Instead, it provides an inexpensive default implementation. A good example is the JTA integration. You're free to configure JTA if you need it, but you're not bound to that approach. Where JTA is overkill, you can easily delegate transaction management to the database without changing anything but configuration.

Hibernate also supports many lightweight solutions for logging and collections (Apache Commons), database access (JDBC), and enterprise containers (Spring). You can deploy with richer J2EE architectures, but Hibernate works perfectly well with Tomcat and MySQL.

7.4.5.1 Going against the grain

At some point, many of the more revolutionary successful frameworks reject conventional wisdom. For Hibernate, three crucial decisions played a significant role in its success:


Reflection is too slow

In fact, reflection is much slower than a direct method invocation. For a persistence framework, it's a price you're willing to pay because database access is inherently so expensive.


A query language must be fully object-oriented

Instead of starting with the premise that a query language for an object-oriented framework must return pure objects, the Hibernate query language started with SQL. To use a query language as close to SQL as possible, it needed to support scalars and aggregates.


A persistence model must provide a shared, common object model

Instead of letting each application have a private cache with a private object model in each session, EJB applications share one major object model across all applications. This approach is a shared, common object model. EJB vendors theorize that such a design leads to better performance. In practice, a smaller, lighter persistence framework can share a common cache; even with a little extra object creation and destruction, it blows the doors off of EJB implementations.

7.4.6 The Down Side

Of course, no framework is perfect. Hibernate is young and largely unproven. Very few people provide the vision for the framework, and that's a dangerous, perhaps limiting model for growth.

As I write this book, the Hibernate team has fairly limited resources. That might be a good thing: such a situation works against unnecessary bloat. It also may hinder the team's ability to improve the framework in meaningful ways. As the project grows, additional programmers will naturally contribute. That's a double-edged sword; many open source projects do not manage growth well. Additionally, Hibernate has been subsumed into the JBoss suite of applications. The JBoss relationship will probably make better-paid support available, making it more attractive for some commercial applications.

Other commercial frameworks, such as Solarmetric's Kodo JDO, produce cleaner and faster SQL, if some of my DBA contacts are to be believed. It makes sense, because that product has been out longer and has a larger team of full-time programmers to help.

Earlier editions of Hibernate had aggressive marketing language criticizing JDO's use of byte code enhancement. Ironically, byte code enhancement may turn out to be a better method than reflection for implementing persistence. Hibernate had early success with reflection only to hit a wall when adding performance enhancements like lazy loading. The proven byte code enhancement techniques common in the JDO marketplace may yet provide a faster, more flexible means of achieving transparent persistence. Hibernate's inclusion of CGLib is an early indication of the limitations of reflection; CGLib provides more flexible lazy loading through, you guessed it, byte code enhancement. In addition, although byte code enhancement has taken some hits in recent years, it's the technology that powers many of the aspect-oriented frameworks.

7.4.6.1 Alternatives

Hibernate is not the only framework that supports transparent persistence. For many projects, it's not even the best way. If you're willing to pay for a persistence framework and you like open standards but abhor EJB, explore JDO. A number of good implementations exist. My favorite is Kodo JDO. It probably generates the cleanest, prettiest SQL. Even a DBA that I know was impressed. It's a framework that uses byte code enhancement to achieve better transparency, supporting more Java constructs than most other products.

Velocity is not a persistence framework, but you can use this code generator to generate data access objects and transparent models. Sometimes, persistence frameworks are simply overkill. Template-based technologies often give you better access to SQL than other alternatives.

OJB is another open source framework, under the umbrella of Apache. It's got a number of usage models, including ODMG, EJB, and JDO. I know many developers who use it and like it, although I haven't had much experience with it. If you're a pure Oracle shop, you may consider TopLink. It was once the top object-relational mapping tool. Interest has waned since the Oracle acquisition.

    Previous Section  < Day Day Up >  Next Section