J2EE Developers use Data Access Object Dao design modes to separate low-level data access logic to high-level business logic. Implementation DAO mode involves more content than writing data access code. In this article, Java Developers Sean C. Sullivan discusses three often ignored aspects in DAO programming: transactions, exception handling, and logging.
In the past 18 months, I participated in a group consisting of talented software engineers, build customized, web-based supply chain management applications. Our application has a wide range of persistent data, including distribution status, supply chain scale (Metrics), inventory, freight invoice, project management data, and user information. We connect to our company's different database platforms with JDBC API and use DAO design patterns throughout the app.
Figure 1 shows the relationship between the application and the data source:
Figure 1. Applications and data sources
Using Data Access Objects (DAO) throughout the application allows us to leave the underlying data access logic to business logic. We build a DAO class that provides GRUD (creation, reading, update, delete) for each data source.
In this article, I will introduce you to build a better DAO implementation strategy and technology. More specifically, I will discuss logs, exception handling, and transactions. You will learn how to combine these three into your own DAO class. This article assumes that you are familiar with JDBC API, SQL and relational database programming.
We will start with an overview of DAO design patterns and data access objects.
DAO Basic DAO Mode is one of the standard J2EE design modes. Developers use this mode to separate the underlying data access operation with high-level business logic. A typical DAO implementation has the following components:
A DAO factory class a DAO interface A specific class data transfer object that implements a DAO interface (sometimes called value object)
The specific DAO class contains the logic of the data accesses the specific data source. In the following section, you will learn techniques for designing and implementing data access objects. For more information on DAO design patterns, please refer to the reference.
The importance of the transaction is important about DAO to remember that they are transactional objects. Each operation performed by DAO - as created, updated, or deleted data - all associated with a transaction. Therefore, the concept of the transaction is particularly important.
The transaction is defined to define the transaction boundary. The J2EE specification describes two models defined: programmmatic and declarative. Table 1 analyzes these two models:
Table 1. Models defined by two transactions
Declarative transaction Definition program transaction boundaries use the EJB deployment descriptor declared transaction properties. The programmer is responsible for writing transaction logic. Runtime Environment (EJB container) automatically manages transactions with these properties. The app passes an API control transaction.
We will focus on programming transactions.
Design considerations As mentioned before, DAO is a transactional object. A typical DAO performs like creation, updates, and deletes such transactional operations. When designing DAO, you must first ask yourself the following questions:
How do you start? How should the transaction end? Which object will be responsible for starting a transaction? Which object will be responsible for ending a transaction? Does DAO are responsible for the beginning and end of the transaction? Does the application need to access data through multiple DAOs? Does the transaction involve a DAO or multiple DAO? Is a DAO call another DAO method?
The answers to the above questions will help you choose the most suitable DAO's transaction strategy. There are two main strategies that define transactions in DAO. One way is to let DAO are responsible for defining the transaction, and the other will deal with the transaction to the object processing of calling this DAO method. If the previous way is selected, the transaction code is embedded in DAO. If the latter method is selected, the transaction define is outside the DAO class. We will use simple code example to help you better understand how every way is working.
Listing 1 shows a DAO with two data operations: creation and update: Listing 1. DAO method
Public Void CreateWarehouseProfile (Whprofile profile);
Public void UpdateWarehouseStatus (Whidentifier ID, STATUSINFO STATUS);
Listing 2 shows a simple transaction. The transaction is defined outside the DAO class. Note How the caller is in this example how to combine multiple DAO operations in a transaction.
Listing 2. Transactions managed by the caller
TX.BEGIN (); // Start the Transaction
Dao.createWarehouseProfile (profile);
Dao.updateWarehouseStatus (ID1, status1);
DAO.UPDATEWAREHOUSTATUS (ID2, STATUS2);
Tx.commit (); // end the transaction
Such a transaction define strategy is especially useful for applications that need to access multiple DAOs in a transaction.
Transactions can be implemented with JDBC API or Java Transaction API (Java Transaction API JTA). The JDBC transaction is bound to be simpler than the JTA transaction, but JTA provides more flexibility. In the following section, I will analyze the mechanisms defined by the transaction.
The transaction with JDBC defines the JDBC transaction is controlled with the Connection object. JDBC Connection Interface (java.sql.connection) provides two transaction mode: Automatic submission and manual commit. Java.sql.connection provides the following methods of controlling transactions:
Public void setAutocommit (boolean) public boolean getautocommit () public void commit () public void rollback ()
Listing 3 shows how to define a transaction with a JDBC API:
Listing 3. Transaction definition with JDBC API
Import java.sql. *;
Import javax.sql. *;
// ...
DataSource DS = ObtainDataSource ();
Connection conn = ds.getConnection ();
Conn.setautocommit (false);
// ...
PSTMT = conn.preparestatement ("Update Movies ...");
PSTMT.SetString (1, "The Great Escape");
PSTMT.ExecuteUpdate ();
// ...
CONN.COMMIT ();
// ...
When using JDBC transactions, you can combine multiple SQL statements into a transaction. One disadvantage of the JDBC transaction is that the range of transactions is limited to a database connection. A JDBC transaction cannot span multiple databases. Below, we will look at how to use JTA to define transactions. Because JTA is not named as JDBC, we first make a profile.
JTA Introduction Java Transaction API (JTA) and its Game Brothers Java Services (Java Transaction Service JTS) provide distributed transaction services for J2EE platforms. A distributed transaction involves a transaction manager and one or more resource managers. A resource manager is any type of persistent data store. The transaction manager is responsible for coordinating communication between all transaction participants. The relationship between the transaction manager and the resource manager is shown in Figure 2:
Figure 2. A transaction manager and resource manager
JTA transactions are stronger than JDBC transaction. The JDBC transaction is limited to a database connection, while JTA transactions can have multiple participants. All the following Java platform components can participate in the JTA transaction: JDBC Connection JDO PersistenceManager Object JMS Queue JMS Topics Enterprise JavaBeans Compliant with the J2EE Connector Architecture Specification Resource Adapter
Use the JTA's transaction to use JTA to perform transactions, the application wants to call the method in the Javax.Transaction.usertransAction interface. Listing 4 shows a typical JNDI query for the UserTransaction object:
Listing 4. A list of UserTransaction objects
JDNI query
Import javax.transaction. *;
Import javax.naming. *;
// ...
InitialContext CTX = New InitialContext ();
Object TXObj = CTX.lookup ("Java: Comp / UsertransAction);
Usertransaction utx = (userTransaction) TXOBJ;
When the application finds the useertransaction object, you can start the transaction, as shown in Listing 5:
Listing 5. Start a transaction with JTA
Utx.begin ();
// ...
DataSource DS = Obtainxadatasource ();
Connection conn = ds.getConnection ();
PSTMT = conn.preparestatement ("Update Movies ...");
PSTMT.SetString (1, "spinal tap");
PSTMT.ExecuteUpdate ();
// ...
Utx.commit ();
// ...
When the application calls commit (), the transaction manager ends the transaction with a two-stage submission protocol.
The JTA method for controlling the transaction Javax.Transaction.UserTransAction interface provides the following transaction control methods:
Public void key () public void problem () public void etstatus () PUBLIC VOID SETROLLLBACKONLIC VOID SETTRANSACTIONTIMEOUT (INT)
Application call begin () Start transaction. The application calls Commit () or rollback () ends the transaction. Refer to the reference information for more information on transaction management with JTA.
Using JTA and JDBC developers typically perform underlying data operations in the DAO class. If you plan to define your transaction with JTA, you need to have a JDBC driver that implements javax.sql.xadatasource, javax.sql.xAconnection and Javax.sql.xareSource interface. A driver that implements these interfaces will be able to participate in the JTA transaction. A XADataSource object is a factory for Xaconnection objects. Xaconnections is a JDBC connection involved in the JTA transaction.
You will need to set XADataSource with the management tool for the application server. You can learn about the relevant guidance from the documentation of the application server and JDBC driver.
The J2EE application queries the data source with JNDI. Once the application finds a data source object, it calls javax.sql.dataasource.getConnection () to get the connection to the database. The XA connection is different from the non-XA connection. Be sure to remember the XA connection to participate in the JTA transaction. This means that the XA connection does not support the automatic submission function of JDBC. At the same time, the application must not call XA.sql.connection.Commit () or java.sql.connection.rollback (). Conversely, applications should use userTransaction.begin (), useertransaction.commit () and serransaction.rollback ().
Choosing the best way we discussed how to define transactions with JDBC and JTA. Every way has its advantages, you need to decide which one is best suited for your application.
In recent projects, our team is to build a DAO class with a JDBC API. These DAO classes can be summarized as follows:
The transaction definition code is embedded in the DAO class. The DAO class uses the JDBC API to define the transaction. The caller cannot define a transaction. The transaction range is limited to a single JDBC connection.
JDBC transactions are not always suitable for complex enterprise applications. If your transaction should span multiple DAO or multiple databases, then the following implementation strategies may be more appropriate:
Transaction is defined by JTA. The transaction definition code is separated from DAO. The caller is responsible for defining the transaction. DAO joins a global affairs.
JDBC mode is attractive due to its simplicity, and JTA ways provide greater flexibility. The implementation you have chosen will depend on the specific needs of the application.
Logging and DAO A good implementation of DAO class will use logging to capture details about their runtime behavior. You can choose to record exceptions, configuration information, connection status, JDBC driver metadata, or query parameters. Logs are useful for all stages of development. I often analyze the application logs when I have been developed, and the application is analyzed.
In this section, I will showcase how to display the code example of how Jakarta Commons Logging is in DAO. Before this, let's review some basic knowledge.
Selecting a log library Many developers use a raw format to log logging: System.out.println and System.err.Println. The PrintLN statement is fast and easy to use, but they do not provide full-featured logging systems. Table 2 lists the log libraries of the Java platform:
Table 2. Log Library of Java Platform
Log library open source code? Urljava.util.logging is not http://java.sun.com/j2se/jakarta log4j is http://jakarta.apache.org/log4j/jakarta commons logging is http://jakarta.apache.org/commons/logging .html
Java.util.logging is a standard API on the J2SE 1.4 platform. However, most developers agreed that Jakarta log4j provides more features and greater flexibility. Log4j is better than java.util.logging is that it supports J2SE 1.3 and J2SE 1.4 platforms.
Jakarta Commons Logging can be used with java.util.logging or Jakarta log4j. Commons logging is a log abstraction layer that isolates the application and the underlying log implementation. With Commons Logging, you can change the underlying log implementation by changing the configuration file. Commons Logging is used in Jakarta Struts 1.1 and Jakarta HttpClient 2.0.
A logging example list 7 shows how to use Jakarta Commons Logging in the DAO class: Listing 7. Jakarta Commons logging in the DAO class
Import org.apache.commons.logging. *;
Class DocumentDaoImpl Implements Documentdao
{
Static Private Final Log Log = logfactory.getlog (DocumentDaoImpl.class);
Public void deletedocument (String ID)
{
// ...
Log.debug ("DELETING Document:" ID);
// ...
Try
{
// ... Data Operations ...
}
Catch (Someexception EX)
{
LOG.Error ("Unable to delete Document", EX);
// ... Handle The Exception ...
}
}
}
Logging is an important part of all task critical applications. If a fault is encountered in DAO, the log usually provides the best information to determine the error position. Join the log to DAO to ensure that you have the opportunity to debug and troubleshoot.
Exceptions in DAO We discussed the transaction definition and logs, and now there is a more in-depth understanding of how to apply them on the data access object. Our third and last discussion topics are abnormal processing. Compliance with several simple exception handling guidance can make your DAO easier, more robust and easier to maintain.
Consider the following questions when implementing the DAO mode:
Does the method in the public interface of DAO throw an exception? If this is, what kind of test is thrown? How to deal with exception in the DAO implementation class?
In the process of using the DAO mode, our team has developed some principles for processing exceptions. Compliance These principles can greatly improve your DAO:
The DAO method should throw a meaningful exception. The DAO method should not throw java.lang.exception. Java.lang.Exception is too general. It does not pass any information about the underlying problem. The DAO method should not throw java.sql.sqlexception. SQLException is a low-level JDBC exception. A DAO should strive to package JDBC instead of the rest of the JDBC to the applies. The method in the DAO interface should only be thrown out when the caller can reasonably expect the caller to handle an exception. If the caller cannot handle this exception in meaningful way, consider throwing an unchecked (running) exception. If the data access code captures an exception, don't ignore it. Ignore the captured exception DAO is difficult to troubleshoot. The exception using the link will convert a low level exception to a high level. Consider defining a standard DAO anomaly class. Spring Framework provides a good set of predefined DAO exception classes.
For more information on exception and exception processing technology, see References.
Implementation: Moviedaomoviedao is a DAO: transaction definition, log, and exception handling of all technologies discussed herein. You can find the Moviedao source code in the Reference section. Code is divided into three packages:
DaoExamples.Exception Daoexamples.Movie daoexamples.moviedemo
This implementation of the DAO mode contains the classes and interfaces listed below:
daoexamples.movie.MovieDAOFactory daoexamples.movie.MovieDAO daoexamples.movie.MovieDAOImpl daoexamples.movie.MovieDAOImplJTA daoexamples.movie.Movie daoexamples.movie.MovieImpl daoexamples.movie.MovieNotFoundException daoexamples.movie.MovieUtilMovieDAO DAO interface defines data operation. This interface has five methods as follows:
public Movie findMovieById (String id) public java.util.Collection findMoviesByYear (String year) public void deleteMovie (String id) public Movie createMovie (String rating, String year, String, title) public void updateMovie (String id, String rating, String Year, string title)
The daoExamples.Movie package contains two implementations of the Moviedao interface. Each implementation uses a different way to perform a transaction, as shown in Table 3:
Table 3. Moviedao implementation
MoviedaoImplmoviedaoImPljta implements a Moviedao interface? Is it DataSource with JNDI? Is it a java.sql.connection object from DataSource? Is DAO defined the transaction internally? Do you use JDBC transactions? Do you use an Xa DataSource? Yes No Is it participating in the JTA transaction? no Yes
Moviedao Demo Application This demo application is a servlet class named DaoExamples.Moviedemo.demoservlet. Demoservlet uses these two MOVIE DAO queries and update movie data in the table.
This servlet shows how to combine the JTA Moviedao and Java Message Service to a transaction, as shown in Listing 8.
Listing 8. Combine Moviedao and JMS code into a transaction
UserTransaction utx = movieutil.getusertransaction ();
Utx.begin ();
Batman = dao.createmovie ("r",
"2008",
"Batman Reloaded");
Publisher = new messagepublisher ();
Publisher.publishTextMessage ("I'll Be Back");
Dao.updatemovie (TopGun.GetId (),
"PG-13",
Topgun.getReleaseYear (),
TopGun.gettitle ());
Dao.deletemovie (legallyblonde.getid ());
Utx.commit ();
To run this demonstration application, you need to configure an XA data source and a non-XA data source on the application server. Then, deploy the daoExamples.ear file. This application can run on any compatible J2EE 1.3 application server. See References to get EAR files and source code.
Conclusion As shown in this article, implementing the DAO mode needs to be more work than writing a low-level data access code. Now you can build better DAO by adding a transaction that is appropriate for your application. Author Blog:
http://blog.9cbs.net/arthas1982/
related articles
Inside Class Loaders: Debugging Author: Andreas Schaefer Persistence in Spring Author: Bruce A. Tate and Justin Gehtland J2SE 1.5 in a Nutshell Author: Calvin Austin Peeking Inside the Box: Attribute-Oriented Programming with Java 1.5, Part 2 Author: Don Schwarz Peeking Inside the Box: Attribute-Oriented Programming with Java 1.5, Part 1 author: Don Schwarz