Migrating an existing Java project for use with Hibernate is a difficult process. And yet I'm not sure if it is worth the work at all.

Some years ago I started a Java project with direct database access using JDBC and SQL. I designed my object model and a relational database schema. Both were optimized independenlty to work optimal in their environment. In order to connect the object world with the relational world, I wrote a clean storage layer, which was responsible for communicating with the database. This worked pretty good. But when Hibernate was becoming more and more popular, I started thinking about migrating to a Hibernate based object mapping.


Well there are some good reasons to use Hibernate:

  1. Simplifying the database access.
  2. Getting more independent from database vendors.
  3. Becoming more flexible when refactoring or enhancing the data model. Especially since there is a good IDE support for refactoring the Hibernate mappings.

So a few days ago I created a project branch and started to work on that. Quickly I realized that this would become much more difficult than expected at first.

I used Eclipse with the Hibernate Tools plugin to generate a set of mapping files based on the existing database schema. Ok, that was an easy start. For every table Hibernate Tools generated a corresponding mapping and every mapping must be associated with a Java class. For most tables this was no problem, but there were a couple mapping tables where I had no suitable class for. In my own code, these tables were joined, but had never its own representation. Now I had the choice to either change my object model to align it with the Hibernate mapping or to tweak the mapping files to use joins either. Since changing the object model would change the whole code base, it was clear that I had to change the mapping. Beside this I was happy with my model and don't like the idea to change it. Later I realized that this would become impossible in one case.

For now I was a bit overwhelmed from the complexity of the 20 mappings generated by Hibernate Tools. So I picked out one by one and started to write DAOs for them. In a first step I tried to load each class stand alone. This was already some work since the conversion of the database types did not always match the types I used in my classes. In my storage layer I have full control over the conversions. But now Hibernate does it automatically with no easy way to change it. This leads to the problem that a database timestamp is converted to the java.sql.Date type. But the SQL date type does not make sense for me. I solved this problem by adding dedicated getters and setter just for Hibernate, where I convert the type immediately into the correct one.

Another problem was that not all tables contain surrogate keys as suggested by Hibernate. For some tables it was more useful to use composite-ids. For these tables I had to write select and update statements. Here I used HQL and the query by example feature from Hibernate and found both as useful.

So after two days I could read and write all objects standalone from the database. Now the tricky part started. I had to model the dependencies. For some classes this was pretty straight forward when there were a surrogate key present. The table relationships were modeled as bags and many-to-one dependencies.

But when it came to the composite-ids, I run into problems. In one special case, I couldn't find a good solution at all. Because I want to avoid classes for the mapping tables, I had to join them in the hibernate mappings using the <join> statement. Hibernate seems to allow joins between two tables only, if they have the same set of primary keys. But in my case one of the tables where using composite-ids, while the other where using just a single foreign key. The result was this error message:

org.hibernate.MappingException: Foreign key (FKF92C56FC70FE07E3:form [form_id])) must have same number of columns as the referenced primary key (form_data [form_id,form_data_id])

The only solution I found here was to join the tables inside the database using views. But this requires that these views are updateable, which is not always possible.

So after my first experiences I see a mixed picture of my new Hibernate based storage layer. While there are some classes that can be handled by Hibernate very easily and I can profit from the powerful IDE support, there are others where I not only had a hard time to implement the mapping. Here complexity of updates and queries is the same as before and some are even more complex. The native queries generated by Hibernate sometimes are inefficient and hard to debug if they do not work as expected. In some cases Hibernate generates a huge amount of queries, where I had just one before. Perhaps there are ways to avoid this by tuning, but then again, where is the advantage of Hibernate over SQL?

Surely it is too early to give a final statement about the pros and cons of migrating an existing project to Hibernate, since there are still a lot of open tasks to do. But I can say already, that switching to Hibernate is a noticeable amount of work and even a serious risk. And I would strongly recommend everybody to first evaluate if the advantages of a migration are worth taking it.


Trackbacks


Trackback specific URI for this entry
    No Trackbacks

Comments


    #1 Pramatr on 02/13/09 at 09:19 PM
    *I started to learn Hibernate in much the same way as you did. The project we worked on was pure Jdbc but it was PITA to manage. We migrated the application over to Hibernate in a piecemeal fashion.

    We generated the entities from the tables we currently had and then tweaked the results to create the domain model we required. Although our model was pretty complicated and messy in places, we still found ways of getting Hibernate to work with it.

    If you are having REAL problems it could be the complexity of the schema, but Hibernate does deal with so many situations. If you're having problems I would thoroughly recommend Java Persistence with Hibernate, it's an excellent reference.
    #2 sud on 02/15/09 at 05:26 AM
    *Hibernate is nice for a green field project. But when working with pre-existing schemas, iBatis provides a much more flexible O-R mapping layer. I suspect some of your challenges with composite foreign keys are more easliy handled in iBatis.

    But iBatis does require much more configuration than Hibernate.
    #2.1 bhaskar on 02/16/09 at 11:32 AM
    *I concur with using iBatis, when you have a fairly complex data model. iBatis + Spring DAOs will give you nice clean separation of domain model & data model, and also relive you with the pain of OR mapping.
    #3 Shantanu Kumar on 02/15/09 at 04:39 PM
    *I have used Hibernate in the past, and also designed large DB schema for use with Hibernate. In my experience it has definitely not been worth it. Performance, DB-design constraints (with Hibernate) and lack-of-agility are the chief reasons.

    I have since moved on to Spring JDBC and Groovy, and have not regretted them so far.
    #4 aryan on 02/15/09 at 06:17 PM
    *I completely agree with you, i used hibernate in production server , the connection pooling is awful even with third-parities like c3p0.
    And in some cases I write SQL code for joining more than two tables !!
    #5 Pramatr on 02/15/09 at 09:32 PM
    *I think the point is the right tool for the right job. Is Hibernate always the right tool? No! Our application was originally written using direct JDBC, we replaced that with Spring Jdbc as a quick fix. Spring Jdbc is great and I'm currently using it and loving it. iBatis is create for some projects also, I've also used that before and loved it. But Hibernate has it's place as well, I think it very much depends on the problem.
    #6 web site design orlando on 01/13/11 at 09:14 PM
    *Good thinking on combining the tables. Congrats on figuring it out. This took me days to learn.
    #7 shams on 11/11/12 at 07:59 PM
    *readers, The below post will be support this article http://www.smashplus.info/2012/11/convert-jdbc-code-in-to-hibernate.html

Add Comment

HTML-Tags will be converted to Entities.
Standard emoticons like :-) and ;-) are converted to images.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA