Wednesday, December 5, 2007

Hibernate Tutorial Review

I'm starting my co-op at Thomson West this week, and things are going swimmingly! I've been introduced to a handful of interesting people and perhaps twice as many new frameworks, some of both that I had never heard of before. Trying to narrow the focus just a little bit and learn something while I've got some downtime on my hands, I haven't been assigned to a particular project yet so I'm going to make my own with an initial focus on the Hibernate library for Java.

Hibernate is a layer that enables creation of persistent objects in Java applications, using a JDBC database as the backing storage layer. I meant to use PostgreSQL as my backing database because it is known as the most advanced database and it is also free, but the tutorial that I am following is based on HSQL, a simple lightweight native Java database engine, so I'm running with that until I have a reason to change it out.

The code is all copied here, all dependent libraries are included for simplicity (exclusively for educational purposes; I have not reviewed the licenses but I'm pretty sure this is non-infringing educational use.) The JDBC drivers are not included as far as I know, you will have to install HSQLDB or PostgreSQL for yourself if you want to follow my tracks and learn with me.

Hibernate code is database-agnostic, a single change in the file hibernate.cfg.xml will alter the storage backend of the app, and that's all it takes to swap out your database for another one. Something like a schema is evident in the file Event.hbm.xml, the hibernate-mapping file, which describes the mapping of objects to database entries for Hibernate.

Hibernate-test01\data\> java -classpath ..\lib\hsqldb.jar org.hsqldb.Server

HSQLDB just runs in a command-line console and you can terminate it when you're done working. Modify the options in hibernate.cfg.xml for hbm2ddl if you want to re-seed the database with fresh tables (maybe you have updated the Event class to include some new data fields and you have modified the hibernate-mapping information, so now the database schema is out of sync.) You will lose any data that you have generated, so it is recommended not to do this in the middle of an experimental trial!

So, now that we've had enough technical jargon to kill a small animal, what does this code do and how can you tinker with it? There are three important classes for which new code has been defined: Event, EventManager, and HibernateUtil.

Event is what is called a JavaBean, that is to say it is very simple in function and supports little else besides manipulation of various data fields; for each Event on our hypothetical calendar, a new Event object is created with a Date, String title, and Long id. These fields are again defined in the hibernate-mapping file Event.hbm.xml, with mappings to columns in a database table.

EventManager is also pretty lightweight, though it is actually doing a lot of work thanks to the support code in Hibernate. The main execution test is in this file, with only two options: list the events in the database, or store a new event with the current time and a default title. The EventManager code does not know about any database, only talks about a Session and from the documentation the current session is associated with the current thread of execution.

To create and store an event:

  1. Get the current session object out of HibernateUtil class
  2. Start a transaction
  3. Create an Event object and populate the data fields
  4. Save the object in the current session
  5. Get the transaction again and commit it back to the database
To show all of the currently listed events:
  1. Get the current session object
  2. Start a transaction
  3. Create a query on the session to grab a List of all objects from the Event table
  4. Commit the transaction and return the resulting List of Events
This leaves HibernateUtil, whose operation is dead simple: instantiate a SessionFactory based on the options in the hibernate configuration file, and hang on to it until EventManager asks for the current Session object. As long as our program is single-threaded and there is only one Session, one transaction at a time, this process remains extremely simple.

Part 2 of the tutorial adds Person objects that can participate in Events, to display the bi-directional association that can be expressed using JavaBean objects and the Hibernate package. I plan to get through this object-association exercise before the close of business today, posting an update to the files in Subversion at least, and completing the primary tutorial.

Tomorrow's post will explore the basic design of business logic for a persistent Casino world with one or more Blackjack tables, and I hope to add some smarts to the Person object by creating some blackjack Players with the capacity to perform card counting. We will also consider the possibility of a user interface and what bits need expressive elements to make this an interesting simulation. Best of all, I may find my keys before the morning comes!

Tonight, resume the tutorial with 1.3. Part 2 - Mapping associations.

2 comments:

yebyen said...

My clients don't want to run Java on their machines because it's too resource-intensive to include a layer of virtualization for the Java Runtime Environment, and they also don't want to use Adobe products because of the exorbitant licensing costs associated with them.

How easily does this translate to PHP5 and Propel? How does Propel compare to Hibernate? Is it difficult to make one of these talk to each other using web services and XML, or perhaps both can operate on the same database backend at the same time? Spring sounds cool and all, but I think I could rather write my public web UI with access to PHP.

yebyen said...

Thomson has a product that we use internally called CTAF: Common Testing Automation Framework. I haven't had a chance to look at it yet, but I would be very surprised if it has support for regular GUI applications as well as web-based form-driven apps.

I'm imagining an app that pulls an initial URL and follows a state-machine diagram along every valid path of execution, submitting an HTTP POST and checking for correct and consistent results for every accepting state.

For best results, don't forget the distinction between valid and correct: a valid input may still be incorrect, and therefore it should still be tested for consistent results.

I want to see a progress meter with a visual frontend for longer tests: some applications may have an inordinate number of possible accepting states, and I want to see logs (ethereal can provide these) of everything passed between server and client across the duration of the test.