
Professional Java.JDK.5.Edition (Wrox)
.pdf
Chapter 6
The mapping file is fairly straightforward once you understand the basic principles in mapping a class to a table in a relational data source. The first element is the beginning <hibernate-mapping/> element. It contains one attribute called package that simply states the package name that the class elements belong to. This is an optional attribute. The <class/> element in the above example maps the class named Employee to a table in a relational database named tblEmployees.
Mapping classes are also required to define an <id/> element, which defines the mapping of a class property to a primary key column in the data source. Primary keys must be available in all the tables you plan to use from a data source. A required child element of the <id/> element, <generator> is used to generate unique identifiers for the instance of the persistent class. The following are the ten built-in generator shortcut names that can ultimately be used.
Generator |
Description |
|
|
Assigned |
Allows the application to specifically assign an identifier to the object |
|
prior to calling the save() method. |
Foreign |
Primarily used in <one-to-one> key associations, this uses an identi- |
|
fier of another object. |
Hilo |
Uses a hi/lo algorithm to generate identifiers of type int, long, or |
|
short. Please be aware that this generator uses a table and a column, |
|
which can be supplied to generate the identifiers. See the Hibernate |
|
documentation for more details. |
Identity |
This generator returns an identifier of type int, long, or short and is |
|
designed for use with identity columns in DB2, HypersonicSQL, MS |
|
SQL Server, and MySQL. |
Increment |
Not to be used with clusters, this generates identifiers of type int, |
|
long, and short that are only unique when a table is currently not |
|
being used by a process to insert data. |
Native |
This generator decides which generator to use based on the data |
|
source. It will pick one of the following to use: hilo, identity, or |
|
sequence. |
Seqhilo |
Generates identifiers of type int, long, or short based upon a hi/lo |
|
algorithm and the given named database sequence. |
Sequence |
This generator returns an identifier of type int, long, or short based on |
|
a sequence in either DB2, PostgreSQL, Oracle, SAP DB, McKoi, or a |
|
generator in Interbase. |
uuid.hex |
Returns a UUID encoded string of hexadecimal digits of length 32. |
uuid.string |
Returns a UUID encoded string of 16 ASCII characters. Not recom- |
|
mended for PostgreSQL. |
|
|
The <property/> element is used to map a Java attribute to a column in a table. You can specify the SQL type, column length, and whether to allow NULL values or not.
316

Persisting Your Application Using Databases
The <set name=”Payroll”> element is an example of how to use Hibernate’s one-to-many mapping features. The <key/> element depicts a foreign key and the <one-to-many> element specifies the relationship between the Employee class and the Payroll class. The <set name=”Payroll”> element also has an attribute <lazy> and it is set to true. This means that the collection of objects will not automatically be populated when first acquired from the data source. It will be populated when the application decides to use it.
Setting Hibernate Properties
Hibernate uses a hibernate.properties file for its main configurations. This file should be stored in your class path and will be used to set configurations such as the following:
Query language constants
Database platform and connection properties
Connection pool settings
Query cache properties
JNDI settings
Transaction API properties
Miscellaneous settings such as showing SQL statements
The ability to store all these settings in a properties file eliminates the need to hard code them into your source code. This is a huge plus when you need to quickly configure your application for a particular architecture.
Using Hibernate’s APIs for Persistence
The basic Hibernate APIs needed to persist objects to a data source are described in this section. In order to persist an object using Hibernate, one of the first requirements is to create a SessionFactory object. A SessionFactory can be created once the net.sf.hibernate.cfg.Configuration object has loaded all the necessary mappings into memory. The following code shows an example of the appropriate way to load the mappings into a Configuration object and how to create a SessionFactory object once the new Configuration object has been populated:
SessionFactory factory;
// Load configurations
Configuration cfg = new Configuration()
.addClass(Category.class)
.addClass(Post.class)
.addClass(Topic.class);
// Create a new SessionFactory factory = cfg.buildSessionFactory();
The Configuration object, cfg, is populated with mappings for the three classes listed in the example: Category.class, Post.class, and Topic.class. Hibernate knows to search for the XML files containing the mappings for the classes in the directory in which they are stored. The XML files should be named with
317

Chapter 6
the prefix of the class name and the suffix hbm.xml. So, for the Category.class file, the name of its XML mapping file should be Category.hbm.xml.
The next steps on your way to persisting your objects are the following:
1.
2.
3.
4.
5.
Open a session with the data source.
Start a transaction.
Create the objects that you want to persist and populate them with data.
Save the objects to the session.
Commit the changes to the data source and close your connection.
The following code illustrates these steps in detail:
//Step 1, open a session with the data source Session snSession = factory.openSession();
//Step 2, start a transaction
Transaction tTransaction = snSession.beginTransaction();
// Step 3, create the objects we want to persist. Category cat = new Category();
cat.setCategoryMsg(“Astronomy”);
cat.setDescription(“Discuss all your Astronomy topics here!”);
//step 4, save the objects to the session snSession.save(cat);
//Step 5, commit the changes and close our session tTransaction.commit();
snSession.close();
Your object Category is now persisted to the data source with little effort. You did not have to know anything about the columns, tables, JDBC types, and so on to accomplish your goal because all the work had been done up front with the XML mapping files. The underlying mapping files and data sources could change without affecting your code.
You can also search for specific data in a data source using Hibernate’s Criteria query API. This API allows you to avoid embedding long SQL strings in queries and provides you with an object-oriented approach to queries. The following is an example of how to query specific information by criteria:
Session snSession = factory.openSession();
Transaction tTransaction = null;
try {
tTransaction = snSession.beginTransaction();
//Retrieve a list of Category objects that have an “id”
//greater than 0.
318

Persisting Your Application Using Databases
List list = snSession.createCriteria(Category.class)
.add( Expression.gt(“id”, new Long(0L)) )
.list();
if (list.size() == 0) return;
Iterator it = list.iterator(); while (it.hasNext()) {
Category cat = (Category) it.next();
System.out.println(“Category Description = “ + cat.getDescription();
}
tTransaction.commit();
}catch (Exception e) {
//Handle Exceptions }finally {
snSession.close();
The code is designed to return all the Category objects that have an id that is greater than 0 into a net.sf. hibernate.collection.List object. Once the List object is populated, you then iterate through the list pulling out the Category objects and printing information from each one to the console. Session.createCriteria is a very versatile API and it should contain enough functionality to satisfy your most complicated searching needs.
The Session operations that can be performed are extensive. The following table describes some of the core functionality. For an extensive list, please see Hibernate’s Java docs.
Method |
Description |
|
|
Transaction beginTransaction() |
Creates a Transaction object and returns it for use. |
Connection close() |
This method completely ends the session and dis- |
|
connects it from the JDBC connections. |
Criteria createCriteria(Class persistentClass) |
This method allows you to create a Criteria |
|
instance and allows you to query the |
|
persistentClass using the specific Criteria |
|
instance for information. |
void delete(Object object) |
Deletes the specific object from the data source. |
List find(String query) |
This method allows you to find specific informa- |
|
tion using an HQL string. |
void saveOrUpdate(Object object) |
Depending on the value of its identifier property, |
|
this method will either save or update the given |
|
instance. Its default behavior is to issue a save() |
|
call. |
void update(Object object) |
This method updates the given instance. |
|
|
319

Chapter 6
Putting It All Together: The Forum Example
The forum example will demonstrate the creation of a fully functional forum where users can create categories, create topics for a specific category, and generate posts that reside inside topics. You will use Hibernate to perform all of the necessary database transactions utilizing its object to relational mapping capabilities. To develop this type of example in JDBC would have been very time-consuming, but by using Hibernate it can be developed relatively quickly.
Understanding the Forum Architecture
The forum is housed in a Web application that resides on an Apache Tomcat server and is accessed via a Web browser by the user. The Web application uses Java Server Pages (JSPs) for the presentation layer, which will process user requests. Figure 6-4 illustrates the architecture of the forum example and where each component resides.
User |
Thin Client |
Web |
|
|
Browser |
|
|
Client |
Server
JSP |
Java |
Pages |
Classes |
MySQL
Server
XML Hibernate
Mappings Properties
TOMCAT Server
Figure 6-4
The Java classes, Hibernate libraries and settings, and JSP pages are all encapsulated in a Web application called forum. The database used is a MySQL database that stands alone as a self-contained DBMS.
320

Persisting Your Application Using Databases
The Forum’s Database
The forum’s database comprises three tables, which are used to store user posts, user topics, and user categories. The table schemas are illustrated in Figure 6-5.
|
|
|
|
There can be many |
|
|
||||
|
|
|
|
topics associated with |
|
|
||||
|
|
|
|
a single Category |
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
tbICategories |
|
|
|
|
|
|
|
|
||
PK |
CategoryID |
|
|
|
|
|
|
There can also be |
||
|
|
|
|
|
many posts associated |
|||||
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
||||||
|
Category |
|
|
|
|
|
|
with a single Topic |
||
|
Description |
|
|
tbITopics |
|
|
|
|
||
|
|
|
|
PK |
|
TopicID |
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Topic |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TopicAuthor |
|
|
|
|
|
|
|
|
FK1,I1 |
CategoryID |
|
|
tbIPosts |
|
|
|
|
|
|
|
|
|
|
PK |
PostID |
|
Post
PostAuthor
DatePosted
FK1,I1 TopicID
Figure 6-5
The tblCategories table is used to store category information. An example of a category would be music. Each category could then have subcategories called topics. The tblTopics table stores information on a specific topic such as what category it belongs to, who created the topic, and the description of the topic itself. An example of a topic that could fall under the category astronomy could be telescopes. Users would post information to the different topic areas such as questions or technical information. The tblPosts table stores topic posts that users have submitted. This table stores information on posts such as who posted the information, what topic the post belongs to, the date the post occurred, and of course the post itself.
The Forum’s File Structure
The forum example utilizes the Apache Tomcat server to host your Web application. Because of this, Hibernate must be configured in such a way that it will play nicely with Tomcat. You must put your JDBC driver that you wish to use in the TOMCAT/COMMON/LIB directory; all the other files will be contained in your forum Web application directory. The required libraries, properties, classes, and JSP files that make the forum example are illustrated in Figure 6-6. Please take note that all the properties files (including the hibernate.properties file) should be contained in the WEB-INF/classes directory.
321

Chapter 6
|
common/lib |
classes |
org/hibernate/forum |
|
mysql.jar |
hibernate.properties |
Category.class |
|
|
log4j.properties |
Driver.class |
TOMCAT |
WEB-INF |
|
Post.class |
|
Topic.class |
||
|
|
|
|
|
web.xml |
|
Category.hbm.xml |
|
|
|
Post.hbm.xml |
|
webapps/forum |
lib |
Topic.hbm.xml |
|
|
||
|
index.jsp |
cglib-2.0-rc2.jar |
|
|
newcategory.jsp |
commons-collections-2.1.jar |
|
|
newpost.jsp |
commons-logging-1.0.3.jar |
|
|
newtopic.jsp |
dom4j-1.4.jar |
|
|
post.jsp |
ehcache-0.6.jar |
|
|
topic.jsp |
hibernate2.jar |
|
|
|
log4j-1.2.8.jar |
|
|
|
odmg-3.0.jar |
|
Figure 6-6
The Forum’s User Interface
The forum’s user interface comprises six JSP pages. Three are used for displaying categories, topics, and posts; the other three are used for submitting categories, topics, and posts. The first user interface shown in Figure 6-7 is the interface for viewing categories. Its filename is index.jsp and it is the first page that the user will see upon accessing the forum webapp. This page retrieves the categories using Hibernate, which are in turn contained in the table tblCategories of the forum database.
Figure 6-7
322

Persisting Your Application Using Databases
The second user interface (UI) shown in Figure 6-8 is the interface used for displaying topics that are stored in the table tblTopics of the forum database. The user would first need to select a category from the category user interface, which would then trigger the topic UI to display the topics related to that specific category. The topic UI knows which category it belongs to because a parameter (cid) is passed to the underlying JSP (topic.jsp) that represents the category ID.
Figure 6-8
The third user interface shown in Figure 6-9 is the interface used to display posts that are associated with a particular topic. These posts are stored in the table tblPosts of the forum database. The user would first need to select a topic from the topic user interface which would display the post UI and display the appropriate posts. The post UI obtains the topic ID through a parameter (TID) that is passed to its JSP (post.jsp).
Figure 6-9
The other three interfaces are used for submitting new posts (newpost.jsp), topics (newtopic.jsp), and categories (newcategory.jsp). These interfaces and all the source code can be found at http://www.wrox.com.
323

Chapter 6
The Forum’s Code
The forum is made up of Java Server Pages (JSPs), which interact with the Hibernate API. The mapping files that Hibernate uses are mapped to Java classes, which you created by hand. As stated earlier, it is possible to have Hibernate generate the classes for you if you downloaded the Hibernate Extensions package. Simply use the utility net.sf.hibernate.tool.hbm2java.CodeGenerator to generate the code after you have created the mapping files.
The first code example I will show you is the Category class and its mapping file, Category.hbl.xml. Here is the Category mapping file:
<?xml version=”1.0”?>
<!DOCTYPE hibernate-mapping PUBLIC “-//Hibernate/Hibernate Mapping DTD 2.0//EN”
“http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd”>
<hibernate-mapping package=”org.hibernate.forum”>
<class name=”Category” table=”tblcategories”> <id name=”id” column=”CategoryID”>
<generator class=”native”/>
</id>
<property name=”CategoryMsg” column=”`Category`”/> <property name=”Description” column=”`Description`”/>
</class>
</hibernate-mapping>
The element <hibernate-mapping> contains a package attribute that specifies the package name in which the Category class is contained. In this case, it is org.hibernate.forum. The <class> element has an attribute called name, which is the name of the Java class to use, and a table element called tblcategories that specifies the name of the table to which the class maps. The <id> element has a attribute called name, which has a value of id. This id value is the name of an attribute in the Category Java class. The column attribute of <id> has a value of CategoryID, which is the column name of the primary key in the table tblcategories. Simply stated, the Java attribute id contained in the class Category now maps to the primary key CategoryID in the table tblcategories of the forum database. The <id> element is required and any tables that you intend to map with must have a primary key. There is a child element called <generator> that is used to automatically generate a unique ID.
The <property> element is used to map Java class attributes to columns in the specified table. Here we are mapping CategoryMsg to column Category and Description to column Description. The code example that follows shows the code for the Category class:
package org.hibernate.forum; import java.util.*;
public class Category
{
private |
Long |
id; |
private |
String |
CategoryMsg; |
324

Persisting Your Application Using Databases
private String Description;
public Long getId() { return id;
}
public String getCategoryMsg() { return CategoryMsg;
}
public String getDescription() { return Description;
}
public void setId(Long nID) { id = nID;
}
public void setCategoryMsg(String string) { CategoryMsg = string;
}
public void setDescription(String string) { Description = string;
}
}
The preceding code shows all the Java class attributes that were referred to in the mapping example. The Java class is also required to provide getter and setter methods for each attribute that is mapped. Hibernate will use these methods to communicate with the class.
Note: The getter and setter method names must be prefixed with get or set and be completed with exact spelling of the attribute name.
The other two classes that are mapped are the Topic and Post classes. They are mapped in the exact same fashion as the preceding examples; therefore, they will not be displayed here. If you are interested in looking at them, the code for the example is available at http://www.wrox.com.
At this point, you haven’t had to use any Hibernate APIs in your code, mainly because Hibernate uses runtime reflection instead of compile-time code. Where you will need to utilize the Hibernate APIs is in the code for the JSPs that access the information from the data source. There are six JSPs in this example: three for viewing data, three for submitting data. I will now demonstrate and explain the post.jsp
and the newpost.jsp. All the other JSPs use similar coding techniques and are less complicated than these two particular JSPs.
The newpost.jsp purpose is to insert a new posting to the database for a specific topic. The code that follows shows the core code that does all the work:
public void createPost(Long lTopicID, String sAuthor, String sPost) throws Exception {
SessionFactory factory;
// Load configurations
Configuration cfg = new Configuration()
.addClass(Category.class)
325