Monday, October 1, 2007

Leveraging Persistence with Hibernate

Most Applications today depend on some sort of persistence layer to maintain state. When developing applications using JEE, the Java Database Connectivity specification (JDBC) empowers developers to use a database as the persistence repository of choice. With the JDBC API, most development efforts become technically feasible as it provides standard CRUD operations to a relational database. Unfortunately, programming with this API can also become cumbersome and repetitive in most cases. The question that remains is "Can we do better?" - It turns out that the answer to this question is "of course!". In fact, there are many other things we could do that is "better", however, for purposes of this entry, I'd like to discuss role and concept of Relational Mappers (ORMs) in the enterprise, and more specifically, Hibernate.

Object Relational Mappers with Java

Although Java is an Object Oriented programming language, the JDBC API lacks the ability to relate to a relational model in a database in a complete object oriented way. This is where Object-Relational Mappers (ORMs) help. Generally speaking, ORMs help model a relational database in terms of Objects that represent a business phenomena. This mapping is maintained in some configuration file (e.g. XML file, annotation, etc). In addition to this kind of mapping, ORMs also provide additional features such as caching, query language support, RDBMS independence (more on this below) and what I like the most, tools to build and monitor this layer among others. Now, having said these, an ORM is not the answer to all solutions. There are times when straight JDBC programming may be more effective, however I've found easier to maintain code written using an ORM than without. Not to mention how elegant the code looks.

Learning Hibernate

Hibernate is an Open Source ORM framework, now part of the JBOSS family of products. As of the time of this writing, Hibernate 3 is the latest release with improved features and nice tools for automatic configuration file generation, code generation, code/table verification, reverse engineering, etc. The documentation is very clear and easy to follow and they now use JIRA to maintain all bug reports. One important thing about Hibernate that I consider strongly is its large number of support for other RDBMs. This means that as long as the code reference Hibernate's API for persistence, an application can be migrated to different databases. This also improves scalability and promotes loose coupling to database specific code. Starting Hibernate for the first time is very simple, but just as much as every other framework, it can become cumbersome if configuration is not designed properly. So, besides being open-source and "elegant", what are some of the reasons when I would suggest to use Hibernate?

Advantages of using Hibernate
Hibernate is a very mature ORM framework, widely used in Enterprise applications. This is not by accident but because it adds value to an application from different perspectives. Here are some of the reasons I would recommend Hibernate:

  • Object Orientation - Hibernate allows development using object oriented constructs when dealing with persistent objects. This means, you can take advantage (programmatically) of associations, polymorphism and inheritance. Depending on your current data model, there may not be a big difference in how a database is represented in terms of objects, thus using Hibernate is a great improvement in your code. I understand that with EJB3, this may not be a unique advantange to Hibernate, however for legacy applications (EJB2, JDBC), this is a clear option.
  • Transparent Persistence - Hibernate maintains all mappings between database tables and objects. This means that all interactions with the database can be done with objects instead of the JDBC API. This level of abstraction adds no more overhead than the average JDBC code. The ability to now write code to objects, without writing SQL code to read/write/delete to a database makes persistence transparent. This means that the persistence layer is now delegated (at least significantly) to Hibernate.
  • Support for polymorphic queries - JDBC supports native SQL when building queries. This can become difficult to maintain and cumbersome to extend. Hibernate's polymorphism support for object mappings allows developers to write queries using the Hibernate Query Language (HQL) using polymorphic objects which can improve the level of abstraction used for modeling data in your queries. Additionally, Hibernate's API promotes object orientation when dealing with queries. (See note below for disadvantages to consider about this feature)
  • Database independence - depending on your business model, an Enterprise Application may need to be deployed in different RDBMs. This is typically dependent upon a business requirement, or a client customization. For this scenario, Hibernate adds value to your application due to the level of abstraction added over the database. This reduced dependency means increased portability of your application. In constrast, nothing in JDBC promotes code to be database neutral and it's up to the developer/architect to ensure portability.
  • Optimized Performance - Hibernate has a powerful caching architecture that allows developers to write code with fewer trips to the database. This is done by virtue of the cached mapped objects as these are "hydrated" from the database and reused when others needed. This kind of caching is difficult to accomplish using straight JDBC.

As an Engineer, one must remember that Hibernate is a tool and not a solution for every problem. Once you used it once, it is very tempting to use it again in every scenario, however one must understand the disadvantages associated with every framework.

Disadvantages in using Hibernate
Depending on your needs, Hibernate may or may not be what you really need. This all depends on different factors (e.g. budget, deadlines, current assets, etc). One must consider all factors before deciding to use Hibernate (just as much as with any other framework).

  • Learning curve - Depending on your current staff, learning Hibernate may be difficult, specially if the application in question is heavily dependant in persistence using already another ORM solution, JDBC or even EJB. Mainly because Hibernate has a lot of publicity does not mean one has to spend budget on it. Although the documentation is very clean, there are many concepts to understand in Hibernate (e.g. dirty checking, caching, lazy-loading, get vs load, etc).
  • Mappings to the Database - The main assumption that all ORMs do is that every table can be modeled to an Object. This is, for the most part true, however you can certainly find cases when representing tables in objects is not necessarily simpler, specially if the database model is not normalized, or poorly designed. Additionally, some DBAs would prefer to use database specific constructs (e.g. triggers, stored procedures) to handle some business logic which may contradict with your intentions in decoupling business logic from persistence. In general, you should not assume that a database can always be represented in terms of objects without understanding all requirements. I recommend getting familiar with the object-relational impedance mismatch for further reference.
  • Performance Bottlenecks - Complex database model may prove to add performance bottlenecks to certain queries (specially if they are polymorphic in nature). Hibernate does an excellent job at building joins for you automatically, but is not able to improve the performance of those queries as a database would do (e.g. analyze the execution plan). This is the kind of optimization that is expected to be done manually. If an Application demands this type of queries in most cases, I would probably consider JDBC instead of Hibernate. It is true that you can also run SQL queries with Hibernate, but if most of the application is doing straight SQL, then we are not using the tool properly (thus defeating the purpose of the ORM).
  • Complex queries - Hibernate provides the "Hibernate Query Language" (HQL) which allows developers to write queries very similar to SQL with object orientation (polymorphism). Depending on the type of inheritance chosen to persist certain schemas, queries can grow in complexity, thus adding complexity to the nature of the query. One could write native SQL queries and make them more efficient than HQL (a DBA should be able to help you here). Once again, this all depends on the type of application that we are dealing with.
Hibernate is a very mature and powerful ORM that in most cases, adds value to your application. Depending on your requirements, Hibernate can reduce the complexity of code maintenance as related to persistence. When dealing with complex data models, one must carefully consider the advantages of using Hibernate (just as much as with any other framework).

No comments: