In my project, I wanted an O/R (object relational) mapping layer. This was to to prevent my code from having lots of low-level, literal database code throughout. There are many choices, and I chose Hibernate. In my first proof of concept, I had actually used Cayenne (I had also used it some at the day job). So what were the aspects of Hibernate that made me want to switch to it, learning curve and all?
First and foremost, Hibernate works with POJO (plain ol’ Java objects) without any special inheritance. A weakness of Cayenne is that your data objects must all extend from Cayenne classes. This can be a big problem if you actually want a specific superclass for them (like, say, extending Map). The Cayenne modeling step is quite cumbersome, and ultimately it creates for you an XML mapping document and shell classes. In Hibernate, you create your own XML document, actually a little simpler than Cayenne’s, and then go to town. No special class inheritance is required. In the Hibernate mapping XML, you specify what table and columns are mapped to the fields in your POJO. That’s all you need to do. At query time, the Hibernate engine will use introspection to find the accessors and load them up with data. The only rule is that you must have accessors (get and set methods) for every attribute you have mapped. This, if you have object Foo with field bar, you need getBar() and setBar() methods, and a Foo.hbm.xml document that describes the mapping. In it, you tell it what table and column the value for “bar” will come from. That’s it. The rest is done automatically.
Hibernate also allows for significant complexity in the mapping. If the mapped table has one-to-many or many-to-many relationships with other mapped tables, you can have them mapped as sets. That way, given an object of type Foo where the bar above is actually one-to-many with the Bar type, you can get a List of associated objects by calling the getBar() method. It’s all very flexible. This relationship can also be in the form of a Map type, where one value in a table is set as the key and another as the value. There is far more complexity available than I have yet used
The aspect that sold me more than any other, though, was the Hibernate Query Language (HQL for short.) It has much of the familar syntax of SQL, but with some wonderfully economical extensions. Because Hibernate knows how your objects relate to the database via the mapping files, you can do complete queries without using the database tables at all. “from com.example.Foo ” would result in a list of Foo objects, one for every row in the table to which it was mapped. Queries can be done by comparing the Hibernate objects, and implicit join logic can even be done by using properties of mapped objects. “from com.example.Foo where Foo.bar.barbar = 1” would select all the objects of Foo that are related to objects of type Bar with field barbar equal to 1. This is much more compact a query than the equivalent SQL would be with joins.
Putting all the above together allows for the situation in which I used it. I began with a database schema, and spent some time mapping that into the Hibernate data objects. This left me with a data object for every table that I needed to interact with. Because all foreign key relationships were mapped in, any access I need to use is transparent to me. If a class is related to a class via 3 intervening join tables, I can access property of the distant class by a.getB().getC().getProperty() . I need not directly instantiate any of those intermediate classes. In fact, I’m not even completely sure if they get instantiated at all. This is how JDO should be. I don’t know how the data comes across the wire, all I know is that I have an object that reflects the data. I can read it and use it, I can change the values and write it back, but I never actually touch the database layer directly.
Used in my Struts web GUI, these objects and their properties are highly useful. I have a list of objects of my type Category attached to the request or the application. Within the Struts JSP, I can iterate over this list access the attributes of this object, as well as any object related to it. This allows for easily setting the displayed name in a selection list to “category.name” while the value is “category.id” and if I need to I can access properties of my related Role objects via direct calls ala “category.role.id”. It makes for the handling of large amounts of dynamic data, which is a common task in web applications and a highly tedious one, nearly effortless. So far, I have been delighted with the choice of Hibernate.