hibernate logo
So this has been a long time coming. I’ve put it off time and time again because there was just so much area I wanted to cover. (see previous post) So finally I’ve decided to cut a bunch of scope and just get this done.

This article is part 2 in a series of 3, which I started way back in November. The project herein is a continuation of that project and the updated project files are included here. I won’t be covering the additional Maven issues in hopes that the first article brought you (the reader) up to speed on those. I will say there are some additional dependencies, so it would be best to use the new files and update your eclipse project files by running the eclipse:eclipse target with Maven.

Hibernate

Hibernate is a great tool. It makes my life easier, and that is good. It started out as a Java only technology. After checking the website it appears they have a .NET version too. Hibernate is a persistence manager. Well you say, “Whatever does that mean?” Well it means that I can map my objects to a set of tables and Hibernate will manage their persistence. Hibernate is language agnostic. For the most part you just tell it what database dialect to use and unless you are using some special features not supported by other databases you can pick a code base up and move it from one DB to another with no change. Another great thing about hibernate is its ability to load an entire object graph, eagerly or lazily, just from querying a single object. For instance let’s say you have a person object, and that person has an address object on it (or even several). Issuing a query for that person will automatically load the address. (For lazy loading it will actually proxy the object and then retrieve the address when the getter is called but that is beyond the scope of the project, yet again, so I won’t go there.) And the last big plus Hibernate brings you, all of this being in my opinion, is updating and keeping object references the same for objects which should be the same and are loaded in 2 different places. Imagine doing all of this in straight JDBC, yuck, I don’t even want to think about that.

Let’s get started!

First things first, download and install MySql, my favorite database. Once you have it all installed, create a user, you can name it whatever you like but I choose test, with a password of… password. If you stray from these values you’ll want to change the configuration that we’ll talk about later. For administrating MySql, if you’re not comfortable with the command line, which I admit can be a bit daunting with a DBMS, then I suggest you also install the MySql GUI tools, they are great and work for Windows, Mac, and Linux. After creating the user, also create a database, again I would call it test, and give the user permissions to access it. I had hoped to do this all using an in memory DB like Derby or Hypersonic, but again out of scope.

The next thing you want to do is to execute the DDL I’ve prepared which is in the application’s src/main/resources/ directory. Creatively enough it’s titled DDL.sql. It’s important for me to note that Hibernate can create this file for you based on either your mapping files or your annotations (more on these later), but again it was out of the scope so I went ahead and prepared one for you.

Down to the nitty gritty.

Now our database is set up and we are ready to get going. First thing’s first, we need to tell spring where our data source is and where does our database server live. It won’t always be localhost, in fact most of the time it shouldn’t be. So we are going to create a datasource bean using spring, which we will later provide to our DAO’s for use with Hibernate. For defining our data source we have several options. I hopefully have chosen the simplest one, which is to declare an instance of spring’s DriverManagerDataSource bean in the spring-web-config.xml file like so…

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
<property name="url"><value>jdbc:mysql://localhost:3306/test</value></property>
<property name="username"><value>test</value></property>
<property name="password"><value>password</value></property>
</bean>

This is the code block you will want to pay attention to if you have used a different username/password than I did. So what is this doing for us? Well this is telling spring to instantiate an object that is a DriverManagerDataSource. On that object it is setting 4 parameters; the JDBC driver to use, the location of the database, the username, and of course the password. Later we will use this bean in our DAO’s so that they can connect to the database. Alternatively we could have used JNDI to locate a defined data source which lives most likely in a server config out there somewhere, but this is out of the scope for what I want to accomplish.

The next thing we need to do is to set up the session factory in our DAO config. We are going to configure our DAO using a file called spring-dao.xml. We load this file in the web.xml file in the context config section.

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="batch_size">15</prop>
<prop key="fetch_size">30</prop>
<prop key="hbm2ddl.auto">false</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>

<property name="dataSource">
<ref bean="dataSource" />
</property>

<property name="annotatedClasses">
<list>
<value>com.weneck.webapplication.domain.Game</value>
</list>
</property>
</bean>

<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>

This does a few things for us. First are the Hibernate properties. We tell Hibernate what dialect to use, some parameters on how to batch queries, and if it should show the SQL being used. After all, Hibernate does still use SQL to communicate with the DB and these statements can be a great way to debug or just learn. Next, we provide the datasource. Remember that datasource bean we just defined, her is where we are using it. Additionally we have a transaction manager, and the location of our annotated classes. For now we only have 1 annotated class in hopes at keeping this simple. Finally we are going to want to set up our JDBC template for our JDBC counterpart. I’ve included a duplicate DAO which uses JDBC instead of hibernate to illustrate the differences.

Domain what?

Lets model our domain. I’m sure by now, especially after applying the DDL you have guessed our domain is a simple object representing a video game. Now we need to model our object in the java world. Take a look at Game.java. At its heart Game has 4 attributes; id, title, platform, and description. What isn’t as clear, perhaps are the annotations marking up the class everywhere. These are JPA standard annotations, which are compatible with Hibernate and tells hibernate what to do with these objects. Let’s take a closer look.

  • @Entity – this tells hibernate that this class should be considered an entity. Easy enough right?
  • @Table(name=’games’) – this tells hibernate what table in the database this entity maps too, still easy.
  • @Id – This tells hibernate that this column/attribute should be considered the primary key of the entity. For composite primary keys you should take a look at the documentation for @EmbeddedId and @Embeddable.
  • @GeneratedValue(strategy=GenerationType.IDENTITY) – this is perhaps a more vague annotations, in our case MySql supports auto_increment, this is a good thing, it means that objects inserted will automatically receive the next value for their id column. Other languages (*cough* I’m looking at you Oracle) do not support this, in that case you need to define a sequence, and tell Hibernate to use the sequence with @SequenceGenerator and a different strategy for the @GeneratedValue annotation. Man, I need to stay on topic.
  • @Column(name=”id”) – this is hopefully the easiest one to understand, what column in the table does this attribute map to.

There are a ton of other useful annotations, including adding constraints @NotNull, where clauses that are ever present @Where, and mapping @OneToOne, @ManyToOne, @OneToMany, and @ManyToMany relationships.

The DAO Layer

Next we need to write our DAO’s. As a general rule and a good practice, DAO’s should not contain any logic, but merely manage objects persistence to and from the database. This isn’t always possible, but something to think about when writing your DAOs. I’ve started by creating a GameDao.java interface. We want to be able to list all of our games, search our games, and save a game. So these are the 3 methods I’ve defined in my DAO. There is a JDBC implementation of this DAO in GameDaoJDBCImpl.java and a Hibernate implementation at GameDaoImpl.java. Once these are written we need to define them in the spring-dao.xml file, and provide them with the data source or the session factory depending on their implementation. Notice each DAO extends a different spring helper class for providing common functionality.

For the hibernate side there are a few important built in methods for managing your domain. Load and Get are good ones, simply call getHibernateTemplate().load(Class.class, Id); or getHibernateTemplate().get(Class.class, Id); specifying the class you want to load along with the primary key you specified with the @Id or @EmbeddedId anotations in the model class. That’s it, the object will come back, properly typed and everything. The loadAll method is similar but you need not specify an id and you get all the objects of the type Class.class. Save is pretty simple, though in my opinion should not be used. It takes an object and saves it. Easy! But it’s my preference to instead use saveOrUpdate, since this will save a new object or as the name suggest update an existing one, thusly killing two birds with one stone. Update, well, if you read that last sentence you know how I feel about update. Delete, pretty easy this one, it deletes the object.

Now we are getting to some of the fun methods. Find will return a typed list of object that meet the criteria supplied in the HQL statement. Whoah, HQL, what’s that? Well it’s nearly identical to SQL, only you can use the java entity name and attribute name of those entities instead of having to reference the column names directly. This includes automatically joining the attributes that might be joined into the entity using some of the @OneToOne etc… anotations. Last there is Execute. It again does as it says, will execute a statement, usually a ddl statement tough it doesn’t have to be.

Spring Services

Normally here is where I would tell you to create your services, configure them in the spring-service.xml file, and put any logic in these classes. In this simple example however, we aren’t really coding any logic, so we’ll bypass this important layer of the web application.

The Results

Fire up that server and open a browser to http://localhost:8080/WebApplication/test/

Just for funzies I’ve included a JDBC implementation for comparison. If you look in the TestServlet.init() method on line 28, you can toggle the comment to use this implementation instead. Such a contrite example it doesn’t showcase all the greatness that Hibernate is, but with a little imagination I bet you can see your way through to the possibilities.

Next up…the whole reason for starting this series, Spring 3 MVC. It’s gonna be a good’un.

Leave a Reply

You must be logged in to post a comment. Login »