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

Beginning Apache Struts - From Novice To Professional (2006)

.pdf
Скачиваний:
60
Добавлен:
17.08.2013
Размер:
11.68 Mб
Скачать

368 A P P E N D I X A F R A M E W O R K S F O R T H E M O D E L

public String getPassword(){ return _password;

}

public String setPassword(String password){ _password = password;

}

}

For each bean you want to persist using Hibernate, you have to create an XML description of it, which essentially maps the bean’s properties to tables and columns in your database. The XML mapping for User appears in Listing A-8.

Listing A-8. Hibernate XML Description of the User Bean

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping

PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping>

<class name="net.thinksquared.registration.data.User" table="user">

<id name="userId" type="string" unsaved-value="null">

<column name="user-id" sql-type="char(32)" not-null="true"/>

<generator class="assigned"/> </id>

<property name="password">

<column name="password" sql-type="char(32)" not-null="true"/>

</property>

</class> </hibernate-mapping>

A P P E N D I X A F R A M E W O R K S F O R T H E M O D E L

369

The XML is fairly self-explanatory, and I won’t describe it further in any detail. The essential idea is that you have an XML file that maps your bean to an existing table in the database.

Saving a bean from scratch is a simple three-step process, very similar to saving data with JDBC:

1.Initialize Hibernate.

2.Obtain a Session object.

3.Save the bean using the Session and close the Session.

Step 1 is usually performed once, when the application starts up. Listing A-9 illustrates steps 1 to 3.

Listing A-9. Saving a User Bean with Hibernate

User u = new User(); u.setUserId("kolmogorov"); u.setPassword("turbulence23");

//Step 0: Start Hibernate

Configuration config = new Configuration().addClass(User.class); SessionFactory factory = config.buildSessionFactory();

//Step 1: Get a Session

Session s = factory.openSession();

//Step 2: Save and close

Transaction t = s.beginTransaction(); s.save(u);

t.commit();

s.close();

Remember that the User class is not autogenerated by Hibernate—it’s assumed to be an existing class in your app. Hibernate’s job is to allow you to save instances of User to a database without you having to worry about SQL and databases.

Doing a search for an object is easy, too. Listing A-10 shows how to implement the exists() function to check whether a given user ID exists.

370 A P P E N D I X A F R A M E W O R K S F O R T H E M O D E L

Listing A-10. An Implementation of exists() with Hibernate

public static boolean exists(String userId){

final String QUERY = "select u from u " +

"in class net.thinksquared.registration.data" + " where u.userId = :userId";

Session s = ... //Get a session somehow.

Query q = s.createQuery(QUERY);

try{

q.setString("userId",userId); List l = q.list();

return (l.size() > 0);

}finally{

s.close();

}

}

The QUERY string is an example of the Hibernate Query Language (HQL), which is similar to SQL except that it works for persisted objects.

These examples do not even begin to scratch the surface of Hibernate’s capabilities. But I hope I’ve given you at least some idea of how Hibernate is used.

In a Nutshell...

In this section I’ve provided a very brief overview of the major persistence frameworks, Hibernate and Torque. These frameworks are complex and whole books are devoted to them, so the treatment in this section is very much incomplete. Even so, I hope I’ve given you a good starting point for your own explorations into this area.

Autogenerating LILLDEP Model Classes

I’ve used Lisptorq to generate LILLDEP Model classes. The code for this is in the .\lisp\ subdirectory of the main LILLDEP development folder.

There are three database tables:

A P P E N D I X A F R A M E W O R K S F O R T H E M O D E L

371

CONTACT, which stores contact information (see Lab 6)

COLLECTION, which stores a collection’s name and notes

COLLECTION_MAP, which stores the actual contacts that go into a collection

To use Lisptorq to generate these classes, you first create a LISP file describing the three tables, as in Listing A-11.

Listing A-11. models.lisp, the Lisptorq LISP File to Autogenerate LILLDEP Model Classes

(import lisptorq.lisp)

define database

(

(contact

(contact_id (PRIMARY REQUIRED INTEGER AUTO)) (name ((VARCHAR 1024)))

(designation ((VARCHAR 1024))) (department ((VARCHAR 1024))) (email ((VARCHAR 255)))

(tel ((VARCHAR 255))) (fax ((VARCHAR 255)))

(company ((VARCHAR 1024))) (address ((VARCHAR 1024))) (postcode ((VARCHAR 16)))

(website ((VARCHAR 255))) (activity ((VARCHAR 2048))) (classification ((VARCHAR 16))) (memo ((VARCHAR 2048)))

)

(collection

(collection_id (PRIMARY REQUIRED INTEGER AUTO)) (name ((VARCHAR 1024)))

(memo ((VARCHAR 2048)))

)

 

(collection_map

 

(collection_id

(REQUIRED INTEGER (FOREIGN collection)))

(contact_id

(REQUIRED INTEGER (FOREIGN contact)))

)

 

)

372 A P P E N D I X A F R A M E W O R K S F O R T H E M O D E L

(lisptorq:set database-name

lilldep)

(lisptorq:set database-type

derby)

(lisptorq:set derby-home

./dbase)

(lisptorq:set package

net.thinksquared.lilldep.database)

(lisptorq:generate database)

To autogenerate the Model classes from this definition, simply put the JAR files jlisp.jar and lisptorq.jar in your classpath, and call the Loader class, like so:

java -classpath jlisp.jar;lisptorq.jar net.thinksquared.jlisp.Loader models.lisp

This will generate all your Model and helper classes, including a DatabaseSetup class, which you can call to create the tables on the database. For a tutorial on using Lisptorq, see www.thinksquared.net/dev/lisptorq/.

Unfortunately, as for LILLDEP, we’ll have to use two different derby-homes: one when the database is initialized for the first time, and the other when it is deployed on Tomcat. This means that you’ve got to create the class twice, or manually change the static section that sets up derby-home in Database.java to that listed in Listing A-12.

Listing A-12. A Tweak to Database.java

//set path to database

String catalinaHome = System.getProperty("catalina.home"); if(catalinaHome == null){

//we are called from an pre-install program System.setProperty("derby.system.home","./dbase");

}else{

//we are on a Tomcat servlet System.setProperty("derby.system.home",

catalinaHome + "/webapps/lilldep/dbase");

}

A P P E N D I X A F R A M E W O R K S F O R T H E M O D E L

373

Useful Links

The Derby project: http://incubator.apache.org/derby/

For more on ACID: http://en.wikipedia.org/wiki/ACID

Hibernate: www.hibernate.org/

Torque: http://db.apache.org/torque/

Lisptorq: www.thinksquared.net/dev/lisptorq/

A P P E N D I X B

■ ■ ■

Commonly Used Classes

This appendix describes selected servlet and Struts classes. Please note that not all functions on a class are shown—only the ones I believe you might find useful.

The documentation for the Struts classes (Action, ActionForm, ActionMessage,

ActionMessages, ActionError, ActionErrors, ActionMapping, FormFile, ComponentContext, and ExceptionHandler) has been adapted from Apache’s JavaDocs for those classes, and is reproduced here for your convenience under the Apache License. A copy of the Apache License is available at www.apache.org/licenses/LICENSE-2.0.

javax.servlet.http.HttpServletRequest

This class encapsulates an incoming HTTP request. It is used to store or retrieve objects that have request scope (using get/set/removeAttribute()). You may also store session scope objects on it by first using getSession() to acquire an HttpSession object (see the next section).

Return Type

Function

Comments

Object

getAttribute(String name)

Returns the value of the named

 

 

attribute as an Object, or null if no

 

 

attribute of the given name exists

void

removeAttribute(String name)

Removes an attribute from this

 

 

request

void

setAttribute(String name,Object o)

Stores an attribute in this request

HttpSession

getSession()

Returns the current session asso-

 

 

ciated with this request, or if the

 

 

request does not have a session,

 

 

creates one

String

getParameter(String name)

Returns the value of a request

 

 

parameter as a String, or null

 

 

if the parameter does not exist

 

 

 

375

376

A P P E N D I X B C O M M O N L Y U S E D C L A S S E S

javax.servlet.http.HttpSession

As its name implies, HttpSession is used to store session-scoped variables. It has get/set/ removeAttribute() functions, identical to HttpServletRequest.

Return Type

Function

Comments

Object

getAttribute(String name)

Returns the object bound

 

 

with the specified name

 

 

in this session, or null if

 

 

no object is bound under

 

 

the name

void

removeAttribute(String name)

Removes the object

 

 

bound with the specified

 

 

name from this session

void

setAttribute(String name, Object value)

Binds an object to this

 

 

session, using the name

 

 

specified

String

getId()

Returns a string

 

 

containing the unique

 

 

identifier assigned to this

 

 

session

 

 

 

org.apache.struts.action.ActionMessage

ActionMessage encapsulates a single locale-independent message. Only the constructors of ActionMessage are important to webapp developers.

Constructor

Comments

ActionMessage(String key)

ActionMessage(String key, Object value0)

ActionMessage(String key, Object[] values)

ActionMessage(String key, Object value0, Object value1)

ActionMessage(String key, Object value0, Object value1, Object value2)

ActionMessage(String key, Object value0, Object value1, Object value2, Object value3)

Constructs an action message with no replacement values

Constructs an action message with the specified replacement values

Constructs an action message with the specified replacement values

Constructs an action message with the specified replacement values

Constructs an action message with the specified replacement values

Constructs an action message with the specified replacement values

A P P E N D I X B C O M M O N L Y U S E D C L A S S E S

377

org.apache.struts.action.ActionMessages

This class is used to store multiple ActionMessages.

Return Type

Function

Comments

void

add(String property,ActionMessage message)

Adds a message to the set

 

 

of messages for the specified

 

 

property

boolean

isEmpty()

Returns true if there are no

 

 

messages recorded in this

 

 

collection, or false otherwise

 

 

 

ActionMessages also has a static String variable called GLOBAL_MESSAGE, which is a property name marker to use for global messages (as opposed to those related to a specific property).

org.apache.struts.action.ActionErrors

ActionErrors is a subclass of ActionMessages, and its sole use is as the return value of ActionForm’s validate(). All of the functions and properties on this class have been deprecated. You should refer to functions or properties on ActionMessages instead.

org.apache.struts.action.ActionMapping

ActionMapping holds information about the valid “next” pages for a particular form handler.

Return Type

Function

Comments

ActionForward

findForward(String name)

Finds and returns the ActionForward

 

 

instance defining how forwarding to

 

 

the specified logical name should be

 

 

handled

ActionForward

getInputForward()

Gets the context-relative path of the input

 

 

form to which control should be returned

 

 

if a validation error is encountered

 

 

 

org.apache.struts.action.Action

An Action is an adapter between the contents of an incoming HTTP request and the corresponding business logic that should be executed to process this request. Struts will select an appropriate Action for each request, create an instance (if necessary), and call the