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:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"https://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
[...]
</hibernate-mapping>
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:
<hibernate-mapping>
<class name="events.Event" table="EVENTS">
</class>
</hibernate-mapping>
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:
<hibernate-mapping>
<class name="events.Event" table="EVENTS">
<id name="id" column="EVENT_ID">
<generator class="native"/>
</id>
</class>
</hibernate-mapping>
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 native
, which picks the best strategy depending on the configured database (dialect). Hibernate 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:
<hibernate-mapping>
<class name="events.Event" table="EVENTS">
<id name="id" column="EVENT_ID">
<generator class="native"/>
</id>
<property name="date" type="timestamp" column="EVENT_DATE"/>
<property name="title"/>
</class>
</hibernate-mapping>
Just as with the id
element, the name
attribute of the property
element tells Hibernate which getter and setter methods to use. So, in this case, Hibernate will look for getDate()/setDate()
, as well as getTitle()/setTitle()
.
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 (which is of java.util.Date
) should map to a SQL date
, timestamp
, or time
column. We preserve full date and time information by mapping the property with a timestamp
converter.
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 is a convention in the Hibernate developer community. The directory structure should now look like this:
.
+lib
<Hibernate and third-party libraries>
+src
+events
Event.java
Event.hbm.xml
We continue with the main configuration of Hibernate.