Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Professional Java.JDK.5.Edition (Wrox)

.pdf
Скачиваний:
39
Добавлен:
29.02.2016
Размер:
12.07 Mб
Скачать

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]