Introduction to Hibernate Preface This chapter is an introductory tutorial for new users of Hibernate. We start with a simple command line application using an in-memory database and develop it in easy to understand steps. This tutorial is intended for new users of Hibernate but requires Java and SQL knowledge. It is based on a tutorial by Michael Gloegl, the third-party libraries we name are for JDK 1.4 and 5.0. You might need others for JDK 1.3. Part 1 - The first Hibernate Application First, we'll create a simple console-based Hibernate application. We use an in-memory database (HSQL DB), so we do not have to install any database server. Let's assume we need a small database application that can store events we want to attend, and information about the hosts of these events. The first thing we do, is set up our development directory and put all the Java libraries we need into it. Download the Hibernate distribution from the Hibernate website. Extract the package and place all required libraries found in /lib into into the /lib directory of your new development working directory. It should look like this: This is the minimum set of required libraries (note that we also copied hibernate3.jar, the main archive) for Hibernate. See the README.txt file in the lib/ directory of the Hibernate distribution for more information about required and optional third-party libraries. (Actually, Log4j is not required but preferred by many developers.) Next we create a class that represents the event we want to store in database. The first class Our first persistent class is a simple JavaBean class with some properties: You can see that this class uses standard JavaBean naming conventions for property getter and setter methods, as well as private visibility for the fields. This is a recommended design - but not required. Hibernate can also access fields directly, the benefit of accessor methods is robustness for refactoring. The id property holds a unique identifier value for a particular event. All persistent entity classes (there are less important dependent classes as well) will need such an identifier property if we want to use the full feature set of Hibernate. In fact, most applications (esp. web applications) need to distinguish objects by identifier, so you should consider this a feature rather than a limitation. However, we usually don't manipulate the identity of an object, hence the setter method should be private. Only Hibernate will assign identifiers when an object is saved. You can see that Hibernate can access public, private, and protected accessor methods, as well as (public, private, protected) fields directly. The choice is up to you and you can match it to fit your application design. The no-argument constructor is a requirement for all persistent classes; Hibernate has to create objects for you, using Java Reflection. The constructor can be private, however, package visibility is required for runtime proxy generation and efficient data retrieval without bytecode instrumentation. Place this Java source file in a directory called src in the development folder. The directory should now look like this: +src Event.java]]> In the next step, we tell Hibernate about this persistent class. The mapping file Hibernate needs to know how to load and store objects of the persistent class. This is where the Hibernate mapping file comes into play. The mapping file tells Hibernate what table in the database it has to access, and what columns in that table it should use. The basic structure of a mapping file looks like this: [...] ]]> Note that the Hibernate DTD is very sophisticated. You can use it for auto-completion of XML mapping elements and attributes in your editor or IDE. You also should open up the DTD file in your text editor - it's the easiest way to get an overview of all elements and attributes and to see the defaults, as well as some comments. Note that Hibernate will not load the DTD file from the web, but first look it up from the classpath of the application. The DTD file is included in hibernate3.jar as well as in the src/ directory of the Hibernate distribution. We will omit the DTD declaration in future examples to shorten the code. It is of course not optional. Between the two hibernate-mapping tags, include a class element. All persistent entity classes (again, there might be dependent classes later on, which are not first-class entities) need such a mapping, to a table in the SQL database: ]]> So far we told Hibernate how to persist and load object of class Event to the table EVENTS, each instance represented by a row in that table. Now we continue with a mapping of the unique identifier property to the tables primary key. In addition, as we don't want to care about handling this identifier, we configure Hibernate's identifier generation strategy for a surrogate primary key column: ]]> The id element is the declaration of the identifer property, name="id" declares the name of the Java property - Hibernate will use the getter and setter methods to access the property. The column attribute tells Hibernate which column of the EVENTS table we use for this primary key. The nested generator element specifies the identifier generation strategy, in this case we used increment, which is a very simple in-memory number increment method useful mostly for testing (and tutorials). Hibernate also supports database generated, globally unique, as well as application assigned identifiers (or any strategy you have written an extension for). Finally we include declarations for the persistent properties of the class in the mapping file. By default, no properties of the class are considered persistent: ]]> Just as with the id element, the name attribute of the property element tells Hibernate which getter and setter methods to use. Why does the date property mapping include the column attribute, but the title doesn't? Without the column attribute Hibernate by default uses the property name as the column name. This works fine for title. However, date is a reserved keyword in most database, so we better map it to a different name. The next interesting thing is that the title mapping also lacks a type attribute. The types we declare and use in the mapping files are not, as you might expect, Java data types. They are also not SQL database types. These types are so called Hibernate mapping types, converters which can translate from Java to SQL data types and vice versa. Again, Hibernate will try to determine the correct conversion and mapping type itself if the type attribute is not present in the mapping. In some cases this automatic detection (using Reflection on the Java class) might not have the default you expect or need. This is the case with the date property. Hibernate can't know if the property will map to a SQL date, timestamp or time column. We declare that we want to preserve full date and time information by mapping the property with a timestamp. This mapping file should be saved as Event.hbm.xml, right in the directory next to the Event Java class source file. The naming of mapping files can be arbitrary, however the hbm.xml suffix became convention in the Hibernate developer community. The directory structure should now look like this: +src Event.java Event.hbm.xml]]> We continue with the main configuration of Hibernate. Hibernate configuration We now have a persistent class and its mapping file in place. It is time to configure Hibernate. Before we do this, we will need a database. HSQL DB, a java-based in-memory SQL DBMS, can be downloaded from the HSQL DB website. Actually, you only need the hsqldb.jar from this download. Place this file in the lib/ directory of the development folder. Create a directory called data in the root of the development directory - this is where HSQL DB will store its data files. Hibernate is the layer in your application which connects to this database, so it needs connection information. The connections are made through a JDBC connection pool, which we also have to configure. The Hibernate distribution contains several open source JDBC connection pooling tools, but will use the Hibernate built-in connection pool for this tutorial. Note that you have to copy the required library into your classpath and use different connection pooling settings if you want to use a production-quality third party JDBC pooling software. For Hibernate's configuration, we can use a simple hibernate.properties file, a slightly more sophisticated hibernate.cfg.xml file, or even complete programmatic setup. Most users prefer the XML configuration file: org.hsqldb.jdbcDriver jdbc:hsqldb:data/tutorial sa 1 org.hibernate.dialect.HSQLDialect true create ]]> Note that this XML configuration uses a different DTD. We configure Hibernate's SessionFactory - a global factory responsible for a particular database. If you have several databases, use several <session-factory> configurations, usually in several configuration files (for easier startup). The first four property elements contain the necessary configuration for the JDBC connection. The dialect property element specifies the particular SQL variant Hibernate generates. The hbm2ddl.auto option turns on automatic generation of database schemas - directly into the database. This can of course also be turned off (by removing the config option) or redirected to a file with the help of the SchemaExport Ant task. Finally, we add the mapping file(s) for persistent classes. Copy this file into the source directory, so it will end up in the root of the classpath. Hibernate automatically looks for a file called hibernate.cfg.xml in the root of the classpath, on startup. Building with Ant We'll now build the tutorial with Ant. You will need to have Ant installed - get it from the Ant download page. How to install Ant will not be covered here. Please refer to the Ant manual. After you have installed Ant, we can start to create the buildfile. It will be called build.xml and placed directly in the development directory. Fixing Ant Note that the Ant distribution is by default broken (as described in the Ant FAQ) and has to be fixed by you, for example, if you'd like to use JUnit from inside your build file. To make the JUnit task work (we won't need it in this tutorial), either copy junit.jar to ANT_HOME/lib or remove the ANT_HOME/lib/ant-junit.jar plugin stub. A basic build file looks like this: ]]> This will tell Ant to add all files in the lib directory ending with .jar to the classpath used for compilation. It will also copy all non-Java source files to the target directory, e.g. configuration and Hibernate mapping files. If you now run Ant, you should get this output: ant Buildfile: build.xml copy-resources: [copy] Copying 2 files to C:\hibernateTutorial\bin compile: [javac] Compiling 1 source file to C:\hibernateTutorial\bin BUILD SUCCESSFUL Total time: 1 second ]]> Startup and helpers It's time to load and store some Event objects, but first we have to complete the setup with some infrastructure code. We have to startup Hibernate. This startup includes building a global SessionFactory object and to store it somewhere for easy access in application code. A SessionFactory can open up new Session's. A Session represents a single-threaded unit of work, the SessionFactory is a thread-safe global object, instantiated once. We'll create a HibernateUtil helper class which takes care of startup and makes Session handling convenient. The so called ThreadLocal Session pattern is useful here, we keep the current unit of work associated with the current thread. Let's have a look at the implementation: This class does not only produce the global SessionFactory in its static initializer (called once by the JVM when the class is loaded), but also has a ThreadLocal variable to hold the Session for the current thread. No matter when you call HibernateUtil.currentSession(), it will always return the same Hibernate unit of work in the same thread. A call to HibernateUtil.closeSession() ends the unit of work currently associated with the thread. Make sure you understand the Java concept of a thread-local variables before you use this helper. A more powerful HibernateUtil helper can be found in CaveatEmptor on http://caveatemptor.hibernate.org/ - as well as in the book "Hibernate in Action". Note that this class is not necessary if you deploy Hibernate in a J2EE application server: a Session will be automatically bound to the current JTA transaction and you can look up the SessionFactory through JNDI. If you use JBoss AS, Hibernate can be deployed as a managed system service and will automatically bind the SessionFactory to a JNDI name. Place HibernateUtil.java in the development source directory, next to Event.java: +src Event.java Event.hbm.xml HibernateUtil.java hibernate.cfg.xml +data build.xml]]> This should again compile without problems. We finally need to configure a logging system - Hibernate uses commons logging and leaves you the choice between Log4j and JDK 1.4 logging. Most developers prefer Log4j: copy log4j.properties from the Hibernate distribution (it's in the etc/ directory) to your src directory, next to hibernate.cfg.xml. Have a look at the example configuration and change the settings if you like to have more verbose output. By default, only Hibernate startup message are shown on stdout. The tutorial infrastructure is complete - and we are ready to do some real work with Hibernate. Loading and storing objects Finally, we can use Hibernate to load and store objects. We write an EventManager class with a main() method: We read some arguments from the command line, and if the first argument is "store", we create and store a new Event: We create a new Event object, and hand it over to Hibernate. Hibernate now takes care of the SQL and executes INSERTs on the database. Let's have a look at the Session and Transaction-handling code before we run this. A Session is a single unit of work. You might be surprised that we have an additional API, Transaction. This implies that a unit of work can be "longer" than a single database transaction - imagine a unit of work that spans several Http request/response cycles (e.g. a wizard dialog) in a web application. Separating database transactions from "unit of work from the application user's point of view" is one of Hibernates basic design concepts. We call a long unit of work Application Transaction, usually encapsulating several short database transactions. For now we'll keep things simple and assume a one-to-one granularity between a Session and Transaction. What does Transaction.begin() and commit() do? Where is the rollback() in case something goes wrong? The Hibernate Transaction API is actually optional, but we use it for convenience and portability. If you'd handle the database transaction yourself (e.g. by calling session.connection.commit()), you'd bind the code to a particular deployment environment, in this direct unmanaged JDBC. By setting the factory for Transaction in your Hibernate configuration you can deploy your persistence layer anywhere. Have a look at for more information about transaction handling and demarcation. We also skipped any error handling and rollback in this example. To run this first routine we have to add a callable target to the Ant build file: ]]> The value of the action argument is set on the command line when calling the target: ant run -Daction=store]]> You should see, after compilation, Hibernate starting up and, depending on your configuration, lots of log output. At the end you will find the following line: This is the INSERT executed by Hibernate, the question marks represent JDBC bind parameters. To see the values bound as arguments, or to reduce the verbosity of the log, check your log4j.properties. Now we'd like to list stored events as well, so we add an option to the main method: We also add a new listEvents() method: What we do here is use an HQL (Hibernate Query Language) query to load all existing Event objects from the database. Hibernate will generate the appropriate SQL, send it to the database and populate Event objects with the data. You can create more complex queries with HQL, of course. Now, to execute and test all of this, follow these steps: Run ant run -Daction=store to store something into the database and, of course, to generate the database schema before through hbm2ddl. Now disable hbm2ddl by commenting out the property in your hibernate.cfg.xml file. Usually you only leave it turned on in continous unit testing, but another run of hbm2ddl would drop everything you have stored - the create configuration setting actually translates into "drop all tables from the schema, then re-create all tables, when the SessionFactory is build". If you now call Ant with -Daction=list, you should see the events you have stored so far. You can of course also call the store action a few times more. Part 2 - Mapping associations We mapped a persistent entity class to a table. Let's build on this and add some class associations. First we'll add people to our application, and store a list of events they participate in. Mapping the Person class The first cut of the Person class is simple: Create a new mapping file called Person.hbm.xml: ]]> Finally, add the new mapping to Hibernate's configuration: ]]> We'll now create an association between these two entities. Obviously, persons can participate in events, and events have participants. The design questions we have to deal with are: directionality, multiplicity, and collection behavior. A unidirectional Set-based association We'll add a collection of events to the Person class. That way we can easily navigate to the events for a particular person, without executing an explicit query - by calling aPerson.getEvents(). We use a Java collection, a Set, because the collection will not contain duplicate elements and the ordering is not relevant for us. So far we designed a unidirectional, many-valued associations, implemented with a Set. Let's write the code for this in the Java classes and then map it: Before we map this association, think about the other side. Clearly, we could just keep this unidirectional. Or, we could create another collection on the Event, if we want to be able to navigate it bi-directional, i.e. anEvent.getParticipants(). This is a design choice left to you, but what is clear from this discussion is the multiplicity of the association: "many" valued on both sides, we call this a many-to-many association. Hence, we use Hibernate's many-to-many mapping: ]]> Hibernate supports all kinds of collection mappings, a <set> being most common. For a many-to-many association (or n:m entity relationship), an association table is needed. Each row in this table represents a link between a person and an event. The table name is configured with the table attribute of the set element. The identifier column name in the association, for the person's side, is defined with the <key> element, the column name for the event's side with the column attribute of the <many-to-many>. You also have to tell Hibernate the class of the objects in your collection (correct: the class on the other side of the collection of references). The database schema for this mapping is therefore: | *EVENT_ID | | | | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | | TITLE | |__________________| | AGE | |_____________| | FIRSTNAME | | LASTNAME | |_____________| ]]> Working the association Let's bring some people and events together in a new method in EventManager: After loading a Person and an Event, simply modify the collection using the normal collection methods. As you can see, there is no explicit call to update() or save(), Hibernate automatically detects the collection has been modified and needs to be saved. This is called automatic dirty checking, and you can also try it by modifying the name or the date property of any of your objects. As long as they are in persistent state, that is, bound to a particular Hibernate Session (i.e. they have been just loaded or saved in a unit of work), Hibernate monitors any changes and executes SQL in a write-behind fashion. The process of synchronizing the memory state with the database, usually only at the end of a unit of work, is called flushing. You might of course load person and event in different units of work. Or you modify an object outside of a Session, when it is not in persistent state (if it was persistent before, we call this state detached). In (not very realistic) code, this might look as follows: The call to update makes a detached object persistent again, you could say it binds it to a new unit of work, so any modifications you made to it while detached can be saved to the database. Well, this is not much use in our current situation, but it's an important concept you can design into your own application. For now, complete this exercise by adding a new action to the EventManager's main method and call it from the command line. If you need the identifiers of a person and an event - the save() method returns it. This was an example of an association between two equally important classes, two entities. As mentioned earlier, there are other classes and types in a typical model, usually "less important". Some you have already seen, like an int or a String. We call these classes value types, and their instances depend on a particular entity. Instances of these types don't have their own identity, nor are they shared between entities (two persons don't reference the same firstname object, even if they have the same first name). Of course, value types can not only be found in the JDK (in fact, in a Hibernate application all JDK classes are considered value types), but you can also write dependent classes yourself, Address or MonetaryAmount, for example. You can also design a collection of value types. This is conceptually very different from a collection of references to other entities, but looks almost the same in Java. Collection of values We add a collection of value typed objects to the Person entity. We want to store email addresses, so the type we use is String, and the collection is again a Set: The mapping of this Set: ]]> The difference compared with the earlier mapping is the element part, which tells Hibernate that the collection does not contain references to another entity, but a collection of elements of type String (the lowercase name tells you it's a Hibernate mapping type/converter). Once again, the table attribute of the set element determines the table name for the collection. The key element defines the foreign-key column name in the collection table. The column attribute in the element element defines the column name where the String values will actually be stored. Have a look at the updated schema: | *EVENT_ID | | | |___________________| | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | <--> | *PERSON_ID | | TITLE | |__________________| | AGE | | *EMAIL_ADDR | |_____________| | FIRSTNAME | |___________________| | LASTNAME | |_____________| ]]> You can see that the primary key of the collection table is in fact a composite key, using both columns. This also implies that there can't be duplicate email addresses per person, which is exactly the semantics we need for a set in Java. You can now try and add elements to this collection, just like we did before by linking persons and events. It's the same code in Java. Bi-directional associations Next we are going to map a bi-directional association - making the association between person and event work from both sides in Java. Of course, the database schema doesn't change, we still have many-to-many multiplicity. A relational database is more flexible than a network programming language, so it doesn't need anything like a navigation direction - data can be viewed and retrieved in any possible way. First, add a collection of participants to the Event Event class: Now map this side of the association too, in Event.hbm.xml. ]]> As you see, these are normal set mappings in both mapping documents. Notice that the column names in key and many-to-many are swapped in both mapping documents. The most important addition here is the inverse="true" attribute in the set element of the Event's collection mapping. What this means is that Hibernate should take the other side - the Person class - when it needs to find out information about the link between the two. This will be a lot easier to understand once you see how the bi-directional link between our two entities is created . Working bi-directional links First, keep in mind that Hibernate does not affect normal Java semantics. How did we create a link between a Person and an Event in the unidirectional example? We added an instance of Event to the collection of event references, of an instance of Person. So, obviously, if we want to make this link working bi-directional, we have to do the same on the other side - adding a Person reference to the collection in an Event. This "setting the link on both sides" is absolutely necessary and you should never forget doing it. Many developers program defensive and create a link management methods to correctly set both sides, e.g. in Person: Notice that the get and set methods for the collection are now protected - this allows classes in the same package and subclasses to still access the methods, but prevents everybody else from messing with the collections directly (well, almost). You should probably do the same with the collection on the other side. What about the inverse mapping attribute? For you, and for Java, a bi-directional link is simply a matter of setting the references on both sides correctly. Hibernate however doesn't have enough information to correctly arrange SQL INSERT and UPDATE statements (to avoid constraint violations), and needs some help to handle bi-directional associations properly. Making one side of the association inverse tells Hibernate to basically ignore it, to consider it a mirror of the other side. That's all that is necessary for Hibernate to work out all of the issues when transformation a directional navigation model to a SQL database schema. The rules you have to remember are straightforward: All bi-directional associations need one side as inverse. In a one-to-many association it has to be the many-side, in many-to-many association you can pick either side, there is no difference. Summary This tutorial covered the basics of writing a simple standalone Hibernate application. If you already feel confident with Hibernate, continue browsing through the reference documentation table of contents for topics you find interesting - most asked are transactional processing (), fetch performance (), or the usage of the API () and the query features (). Don't forget to check the Hibernate website for more (specialized) tutorials.