11 million installations can't be wrong

MySQL Journal

Subscribe to MySQL Journal: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get MySQL Journal: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn

MySQL Journal Authors: Greg Schulz, Cloud Best Practices Network, Jayaram Krishnaswamy, Elizabeth White, Jnan Dash

Related Topics: Java EE Journal, Apache Web Server Journal, Eclipse Platform, Java Developer Magazine, MySQL Journal

J2EE Journal: Article

Java Feature — Bringing Together Eclipse,WTP, Struts, and Hibernate

Bringing Together Eclipse,WTP, Struts, and Hibernate

The file in Listing 8 contains two class tags, where each of our domain classes Customer and Order is mapped to the corresponding database table, with each instance variable mapped to a database column. One attribute worth mentioning is "lazy" - we have explicitly set to it to false, the reason being that when lazy is true (default), reading from the database is only done whenever a particular method is accessed. For example, it'll happen only when a getFirstName() is called, rather than pre-reading the whole set of customers right away - when the SQL query is issued. This may sometimes be beneficial when you read a large set of data and want to defer expensive database operations. In our example, we're only reading a small set of customers and don't want additional performance or database access issues to occur later, such as if the database session is closed at that later time, we'll get an exception from Hibernate if we still try to invoke the "lazy" method.

The Hibernate configuration is complete, and we have to modify our CommandExecutor class a bit to use the framework and remove hard-coded SQL code. This class has been used as a singleton for storing data sources and getting database connections. First of all, we'll be adding the instance variable to store the Hibernate session factory. The Hibernate session factory is similar to a data source, except instead of getting database connections from it, we'll be getting Hibernate database sessions. The instance variable will look simply as follows:

private SessionFactory sessionFactory = null;

Next, we want to create an access method for this instance variable (See Listing 9). This will maintain the object state encapsulated, and will also allow using techniques of the lazy initialization (access the data only when needed):

In this method, we initialize a session factory for the first time. Hibernate's Configuration object is used to read the configuration file from the classpath and initialize the framework accordingly.

We've used the executeDatabaseCommand() method before we started using Hibernate to perform our database operations: using the DatabaseCommand interface that required the executeDatabaseOperation() method. Since we now want to use Hibernate, we're going to introduce another method to the DatabaseCommand interface and another one to the CommandExecutor singleton object - this method will execute all of our database operations using Hibernate framework (See Listing 10).

This looks very like the executeDatabaseCommand() method, except that in this case, we're using a Hibernate Session object rather than a normal JDBC connection. The next step would be simply to add the following stub method to the DatabaseCommand interface:

public Object executeHibernateOperation(Session session) throws SQLException;

Now that we've added this new method to the interface, all the classes implementing this interface will be marked with red bullets in the Eclipse workbench, because the classes implementing the interface have to implement all the methods that it requires. We have four classes implementing the database command interface:

public class CreateCustomer implements DatabaseCommand
public class CreateOrder implements DatabaseCommand
public class ListCustomers implements DatabaseCommand
public class ListCustomerOrders implements DatabaseCommand

Hence we have to add an executeHibernateOperation() implementation method to each of them. Let's take a look at the CreateCustomer class first. Its executeDatabaseOperation() method is shown in Listing 11.

This method is fairly long and coding one requires a developer to know JDBC: how to create and execute prepared statements. Also, if one were to change the database from MySQL to some other one, it might require that the developer re-write the SQL because it may differ from one database to another. With Hibernate, you just change the SQL dialect in the hibernate.cfg.xml configuration file. Our corresponding executeHibernateOperation() method is in Listing 12.

In Listing 12 we tell the session object to save our class in the database. No SQL, no JDBC knowledge, no hard-coding of column and table names. If we have to change the table or column name, we don't have to go through possibly multiple lines of code in the application. Hibernate knows how to save the object, whether this object already exists in the database or not (to do an INSERT or UPDATE operation - it performs a check in either the optimistic way (tries to do an UPDATE, and if that fails, INSERT) or pessimistic way (does a SELECT to see if the row exists, if yes, then does UPDATE, otherwise INSERT). We flush the session after the execution of the command to make sure that all the database commands are executed right away without anything left over in the framework's buffer. In a similar fashion we perform the operation for the CreateOrder class.

First, the two operations that we have dealt with (in the JDBC version), CreateCustomer and CreateOrder, are database insert operations. However, one also has to handle database queries to make the application work. For that, we have ListCustomers and ListCustomerOrders commands. Let's look at how we get the customer list.

Listing 13 contains a bunch of JDBC calls. First, create an SQL statement, execute it using hard-coded column and table names, and then go through the ResultSet of the database query and construct a Customer domain object explicitly from each row read from the table, where we also have to remember the column order or names. All those operations are error prone and may become hard to maintain whenever changes to the database tables are required. This is where Hibernate comes to the rescue. It introduces a whole new language called the Hibernate Query Language (HQL), where one doesn't need to query database tables, but rather objects. Our executeHibernateOperation() method will look as in Listing 14.

Once again this method looks pretty similar to the old one, however, there are some significant differences. Here we are using a bunch of Hibernate objects. The first one is a Query class. It lets one create and execute database queries using either HQL (through the createQuery method) or regular SQL (through the createSQLQuery method). Let's look at the HQL we are using here:

from customer in class domain.Customer

Basically we're selecting all the customers identified by the variable customer from the domain.Customer class. Obtaining the iterator of the query lets us put "customers" in any collection. In our case it's ArrayList<Customer>.

A very similar method can be written for the ListCustomerOrders class, but HQL is a tiny bit more complex as you can see in Listing 15.

In this case we use the where-clause in our query. Note that in this where-clause we can use the instance variable of the Order class (custId) to query by. The syntax is similar to Java's dot notation.

Finally we have to update our Struts action classes to invoke the executeHibernateOperation() method instead of the executeDatabaseOperationMethod(). This can be done easily using Eclipse editors.

Exporting an Eclipse Project into WAR
Using WTP tools we can easily export our project into the WAR file to be deployed under Tomcat. Just select the DBTestStruts Web project, then select Export from the File menu. When prompted, select the WAR file, specify the file name, and you'll have the WAR file ready to be deployed in Tomcat.

The goal of this article was to how you how to integrate Struts and Hibernate support into a simple Web application developed using Eclipse and WTP tooling. These frameworks help to improve application maintainability and code reusability, as well as code clarity.

More Stories By Boris Minkin

Boris Minkin is a Senior Technical Architect of a major financial corporation. He has more than 15 years of experience working in various areas of information technology and financial services. Boris is currently pursuing his Masters degree at Stevens Institute of Technology, New Jersey. His professional interests are in the Internet technology, service-oriented architecture, enterprise application architecture, multi-platform distributed applications, and relational database design. You can contact Boris at [email protected]

Comments (10)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.