July 26 2008
Getting Started Quickly with Hibernate Annotations
Tutorial Chapter 1 - Step By Step
Getting started with Hibernate can be tricky, but here’s a step-by-step tutorial that explains exactly what needs to be done to enable your application for hibernate. This chapter covers very basic mapping and persistence.
Download the following archives:
- Hibernate Core (3.3.0_CR1)
- Hibernate Annotations (3.4.0_CR1)
- HSQLDB (1.8.0.10), a lightweight in-memory RDBMS (or use the database of your choice)
Instructions:
- Extract the archives and copy necessary JAR files into your project:
It may seem like quite a few jars, it might not, but this is the minimal set to have a working Hibernate Annotations 3.4.0 application. All of the following files should be contained in your downloads.
Hibernate Annotations hibernate-annotations.jar hibernate-commons-annotations.jar jta.jar (JTA, javax.transaction) Hibernate Core hibernate-core.jar (or hibernate3.jar) ejb3-persistence.jar (javax.persistence) antlr.jar (2.7.6) commons-collections.jar (3.1) dom4j.jar (1.6.1) slf4j-api.jar (1.4.2) cglib.jar (v2) adm.jar (v3) HSQLDB hsqldb.jar
- Add the JARs to your project’s classpath.
- Copy and paste the following source files into your project. We’re going to use some canned configurations in order to get all of this working.
—-
log4j.properties
(Optional) Put this file on your classpath, or in your source folder. Hibernate uses log4j to print output, so if we want to see detailed results, you should set this up.
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.rootLogger=warn, stdout
log4j.logger.org.hibernate=info
log4j.logger.org.hibernate.type=info
log4j.logger.org.hibernate.tool.hbm2ddl=debug
log4j.logger.org.hibernate.transaction=debug—-
MockObject.java
It’s time to create our first object. Notice that this is a simple POJO with two fields: id and version. The id field is a required field, but before you complain, there is a philosophy of database design that dictates every entity table should have its own id column; some disagree with this, but I’ve found it a very convenient practice. Try it out before you pass judgment.
In order to map an object, a few things always need to be done:
- The class must be annotated with @javax.persistence.Entity
- The class must have a @javax.persistence.Id column
- The class must have a default (or undefined) constructor method. This means it must have a constructor that has no arguments.
- The @Version column is how Hibernate performs optimistic locking. If a record has been modified by another transaction, your transaction’s version will be out of date, and an exception will be thrown.
- By default, all fields in your class will be persisted to the database if possible. If there is a field that should not be recorded in the database, mark that field with the @Transient annotation.
- To add new columns in the database, simply add new fields in your object.
import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Version; @Entity @Table(name = "mock_objects") public class MockObject implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", updatable = false, nullable = false) private Long id = null; @Version @Column(name = "version") private int version = 0; public Long getId() { return id; } public int getVersion() { return version; } }
—-
HibernateUtil.java
HibernateUtil is a convenience class that automates configuration, and provides your application access to the active Session. This is where you tell Hibernate about your MockObject class, and where you get a handle to an object that will save, update, delete and etc. your objects.
import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { AnnotationConfiguration config = new AnnotationConfiguration(); config.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"); config.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver"); config.setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:demodb"); config.setProperty("hibernate.connection.username", "sa"); config.setProperty("hibernate.connection.password", ""); config.setProperty("hibernate.connection.pool_size", "1"); config.setProperty("hibernate.connection.autocommit", "true"); config.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider"); config.setProperty("hibernate.hbm2ddl.auto", "create-drop"); config.setProperty("hibernate.show_sql", "true"); config.setProperty("hibernate.transaction.factory_class", "org.hibernate.transaction.JDBCTransactionFactory"); config.setProperty("hibernate.current_session_context_class", "thread"); // Add your mapped classes here: config.addAnnotatedClass(MockObject.class); sessionFactory = config.buildSessionFactory(); } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } }
—-
HibernateDemo.java
Our driver class is very simple; it does the following things:
- Get a handle to Hibernate Session
- Create and persist two new MockObjects
- Print out the generated IDs
import org.hibernate.Transaction; import org.hibernate.classic.Session; public class HibernateDemo { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); Transaction transaction = session.beginTransaction(); MockObject object0 = new MockObject(); MockObject object1 = new MockObject(); session.save(object0); session.save(object1); transaction.commit(); System.out.println("Object 0"); System.out.println("Generated ID is: " + object0.getId()); System.out.println("Generated Version is: " + object0.getVersion()); System.out.println("Object 1"); System.out.println("Generated ID is: " + object1.getId()); System.out.println("Generated Version is: " + object1.getVersion()); } }
And here we are. When you run HibernateDemo, you should have a fully functional Hibernate enabled HSQL database with one table. Play around with adding new fields to your object.
Your output should look something like this:
Object 0 Generated ID is: 1 Generated Version is: 0 Object 1 Generated ID is: 2 Generated Version is: 0
—-
Considering the Forces:
I’d like to note, here, that we’re doing a lot of configuration in the code itself. This is OK if you are relatively sure that you won’t need to be making changes to your data model or back-end configuration very frequently. However, if you know that this is going to happen, I strongly suggest using XML configuration files instead, and you should also consider using traditional Hibernate with XML object-relational mappings. If you build all configuration into your code, every time you change the configuration, you’ll have to recompile / rebuild parts of your system. It’s much easier just to edit a file. However, unless you’re sure, just cross that bridge when you come to it.
A few more things to remember:
Take your time. Don’t give up. Ask questions. READ the forums and documentation.
Hibernate is BIG. It’s a very powerful, very complex tool. It took me a long time to get even a simple object relationship working the way I wanted to. The learning curve is not small, and you will probably be frustrated for a while. I have, however, come to the point where I see so much benefit, that I feel it was completely worth my time to learn.
Configuration is everything. Hibernate can do anything you want: You can use it to tie in to existing database schema; you can use it to run plain SQL queries or stored procedures.
Good luck.
References:
This article is part of a series: Guide to Hibernate Annotations
