So you’ve just finished reading that introduction to Hibernate.  Now you know how to do basic CRUD and queries, these are the things you need to know or do to take your hibernate game to the next level.

Everyone in the java world knows about (or should know about) Hibernate.  It’s a very popular persistence package for Java, handling the nuts and bolts of data persistance.  It also has a package for .NET, but I’m going to be discussing the Java API’s.

Hibernate is incredibly easy to use in simple cases, but I often find developers failing to understand some of the complexities of Hibernate that any developer working with the tech must know:

  1. Read the FAQ’s.  Hibernate’s documentation page links to FAQ’s for each API.  Read these proactively, not just when you have a problem.

  2. Understand the various relationships, and the complexities with each.  Any developer using hibernate should understand the domain, annotations/xml, and generated table structure hibernate will produce with each relationship type.  I don’t mean you need to memorize all their naming conventions, but you must understand how relationships are mapped in the db.

  3. Understand what triggers a query.  This is the biggest trap I see developers fall into.  Consider the following code:

    class Folder {
         private Set files;
         private String name;
         //getters and setters
    }
     
    class File {
         //properties
    }
     
    //in a page
    List folders = session.createQuery("from Folder").list();
    for(Folder folder:folders){
         response.write(folder.getName() + " has "
              + folder.getFiles.size() + " files\n");
    }

    This is fairly straightforward.  We’re outputting folder names and the number of files in each.  But there is a problem.
    Hibernate uses something called lazy loading.  While the details are available elsewhere, the high level description is when you load an object, it’s associated objects aren’t loaded until you use them.  This makes sense, since if you never use something it never gets loaded.  The details of how this works are available in the hibernate docs.  The defaults depend on what parts of hibernate you’re using, and this is all customizable within your hibernate mappings.
    The code above will, unless specifically otherwise mapped, trigger a query per Folder, to load each folder’s file list.  This is triggered by the call to folder.getFiles().size().  Under load (high volume of data and/or usage) this will fall over.  So what’s the solution?  In this case, itemizing the fields you want in the query will solve the problem nicely.
    Simply making everything eager (the opposite to lazy, in other words fetch at initial retrieval time) is NOT a general solution; you end up with huge object graphs being loaded into to memory very often.  Eager is appropriate in many situations, but like everything else, there are costs.

  4. Understand which associations are eager.  Hibernate annotations defaults *-to-one relationships to eager.  This is typically not problematic but create scenarios where a massive amount of joins and object creation takes place.  If you have a many X to one Y relationship, every time you load an X you necessary load the associated Y.  You also load anything which has an eager association with Y.

  5. Always check your code with sql logging on.  After you’ve built something, run through it with sql logging on and make sure the queries being made make sense to you.  If you see extraneous, investigate.  If it isn’t your code, your boss wil be happy if you find stuff like this.

Hibernate’s simplicity in basic use cases belies complex underpinnings.  People who use Hibernate blithely will fall into performance traps.  It is essential that any developer working with Hibernate understand the above; just because Hibernate does the nuts and bolts of JDBC for you isn’t an excuse to be ignorant of what it’s doing.

Comments

Leave a Reply