Home > Guides > Programming > Java

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

Data Access Object Pattern

Last updated Jan 1, 2004.

The Data Access Object Pattern, also known as the DAO pattern, abstracts the retrieval of data from a data resource such as a database. The concept is to "separate a data resource's client interface from its data access mechanism."

The problem with accessing data directly is that the source of the data can change. Consider, for example, that your application is deployed in an environment that accesses an Oracle database. Then it is subsequently deployed to an environment that uses Microsoft SQL Server. If your application uses stored procedures and database-specific code (such as generating a number sequence), how do you handle that in your application? You have two options:

  1. Rewrite your application to use SQL Server instead of Oracle (or add conditional code to handle the differences), or

  2. Create a layer inbetween your application logic and the data access

The Data Access Object pattern does the latter.

The benefits of the DAO pattern are obvious, but the implementation is a little tricky. To properly implement the DAO pattern you need to generate the following components:

  1. DAO Interface

  2. DAO Factory

  3. DAO Implementation classes

  4. Deployment Descriptor Entry

The DAO pattern, in and of itself, does not necessarily require a factory, but in practice you will see the two patterns coupled. The reason is that some mechanism needs to be created to obtain the appropriate implementation class and using a factory is the cleanest implementation.

DAO Interface

The DAO interface defines all the methods that your data access objects will provide. For a database, these include things like inserting, deleting, updating, and retrieving rows. Because it is an interface, the methods will not be implemented. Listing 1 shows a sample DAO interface.

Listing 1. SampleDAO.java

package com.informit.myejb.dao;

public interface SampleDAO
{
 public SampleModel create( long id, String name, String data ) throws 
SampleDAOException;
 public void delete( long id ) throws SampleDAOException;
 public void update( long id, SampleModel model ) throws 
SampleDAOException;
 public SampleModel[] findByName( String name ) throws 
SampleDAOException;
 public SampleModel findById( long id ) throws SampleDAOException;
}

The SampleDAO interface presumes a SampleModel object that represents one unit of data. Listing 2 shows the implementation of this hypothetical class.

Listing 2. SampleModel.java

package com.informit.myejb.model;

public class SampleModel
{
 private long id;
 private String name;
 private String data;

 public SampleModel( long id, String name, String data ) {
  this.id = id;
  this.name = name;
  this.data = data;
 }

 public long getId() {
  return id;
 }

 public String getName() {
  return name;
 }

 public String getData() {
  return data;
 }

 public void setName( String name ) {
  this.name = name;
 }

 public void setData( String data ) {
  this.data = data;
 }
}

The class that eventually uses the implementation of this interface will use it via this interface, and not through the implementation itself.

DAO Implementation

We need a class that performs the actual data access; this will be the function of the DAO implementation class. Its job is to translate the general request for information to a request specific to the data source it represents. For database access, I usually suggest the following:

  • JDBC Generic implementation: this is an implementation that uses only JDBC and standard SQL

  • Database vendor specific implementation number one: e.g. Oracle

  • Database vendor specific implementation number two: e.g. SQL Server

  • Database vendor specific implementation number ...

Listing 3 shows a sample implementation of the DAO implementation class.

Listing 3. SampleDAOJDBCImpl.java

package com.informit.myejb.model;

import java.sql.*;

public class SampleDAOJDBCImpl implements SampleDAO
{
 public SampleModel create( long id, String name, String data ) throws 
SampleDAOException {
  try {
   Connection conn = getConnection();
   PreparedStatement ps = 
     conn.prepareStatement( "INSERT INTO sample VALUES( ?, ?, ? )" );
   ps.setLong( 1, id );
   ps.setString( 2, name );
   ps.setString( 3, data );
   ps.executeUpdate();
   return new SampleModel( id, name, data );
  }
  catch( SQLException e ) {
   throw new SampleDAOException( e );
  }
 }

 public void delete( long id ) throws SampleDAOException {
  // Similar: DELETE FROM sample WHERE id = ?
 }

 public void update( long id, SampleModel model ) throws
 ampleDAOException {
  // Similar: UPDATE sample SET name = ?, data = ? WHERE id = ?
 }

 public SampleModel[] findByName( String name ) throws 
SampleDAOException {
  // Similar: SELECT FROM sample WHERE name = ?
 }

 public SampleModel findById( long id ) throws SampleDAOException {
  // Similar: SELECT FROM sample WHERE id = ?
 }
}

At runtime, this is the class that will perform the data access on our behalf.

DAO Factory

We need a mechanism for determining what class to load at runtime and use in our application. This is the job of the DAO factory class.

The factory class is used in another pattern, the Factory Pattern. The purpose of the factory pattern is to defer the choice of an implementation class until runtime. You ask the factory to create a class that implements a specific interface and (given some piece of additional environmental information), the factory creates the appropriate class.

In the case of an EJB deployment, the additional environmental information is usually specified through the EJB's deployment descriptor. In a stand-alone environment, you can specify it with Java system properties or a configuration file (such as an XML file or properties file).

Listing 4. SampleDAOFactory.java

package com.informit.myejb.dao;

// Import the JNDI classes
import javax.naming.NamingException;
import javax.naming.InitialContext;

public class SampleDAOFactory {

  private static SampleDAO dao = null;
  
  public static SampleDAO getDAO() throws SampleDAOException 
  {
    // If we already have loaded the BookDAO, return it
    if ( dao != null ) {
      return dao;
    }
    
    try {
      InitialContext ic = new InitialContext();
      String className = ( String )ic.lookup( "SAMPLEDAO.Impl" );
      dao = ( SampleDAO )Class.forName( className ).newInstance();
    } 
    catch( NamingException ne ) {
      throw new SampleDAOException( ne );
    } 
    catch( Exception se ) {
      throw new SampleDAOException( se );
    }
    return dao;
  } 
}

The SampleDAOFactory class maintains a static reference to the SampleDAO class. The first time the DAO object is requested, the factory looks up the fully qualified class name of the implementation class specified by the deployment descriptor key: "SAMPLEDAO.Impl". It uses the InitialContext class to access the Java Naming and Directory Interface (JNDI) and then calls its lookup() method to find the String value. Finally, it loads the class dynamically by calling Class.forName() and casting it to SampleDAO.

Deployment Descriptor Entry

The final piece of information to get into the system is the association between "SAMPLEDAO.Impl" and the actual class that implements the SampleDAO interface (com.informit.myejb.dao.SampleDAOJDBCImpl). This is accomplished by creating an <env-entry> entry in the ejb-jar.xml file. Listing 5 shows an excerpt from this file.

Listing 5. Excerpt from ejb-jar.xml

<ejb-jar>
 <enterprise-beans>
  <entity>
   <description>Sample Bean</description>
   <ejb-name>SampleBean</ejb-name>
   <home>com.informit.myejb.ejb.SampleHome</home>
   <remote>com.informit.myejb.ejb.Sample</remote>
   <ejb-class>com.informit.myejb.ejb.SampleEJB</ejb-class>
   <persistence-type>Bean</persistence-type>
   <prim-key-class>com.informit.myejb.ejb.SamplePk</prim-key-class>
   <reentrant>False</reentrant>

   <env-entry>
    <env-entry-name>SAMPLEDAO.Impl</env-entry-name>
    <env-entry-type>java.lang.String</env-entry-type>
    <env-entry-value>com.informit.myejb.dao.SampleDAOJDBCImpl</env-
entry-value>
   </env-entry>
   ...
  </entry>
  ...
 </enterprise-beans>
<ejb-jar>

In this case, we define a java.lang.String key named "SAMPLEDAO.Impl" to be "com.informit.myejb.dao.SampleDAOJDBCImpl". This will make a JNDI entry into any class owned by the SampleBean class.

Summary

The Data Access Object pattern provides a great mechanism for deferring the implementation of data access to an application's runtime. This way, an application can be written without the knowledge of what database it will be connected to during deployment. Furthermore, it supports expandability, as deployment to a new database only requires a new DAO class and the modification of a deployment descriptor.

The Data Access Object pattern does not need to be used exlusively for databases. Rather, you can use it whenever you need to access data from any resource. One very practical example was in an application that could run both over the Internet or stand-alone; in the stand-alone version, the application retrieved its data from the local file system, while in the Internet-based version it retrieved its data by making requests from the server.

Discussions

Read and display the table in the document
Posted Nov 12, 2008 06:01 AM by StrongHead
1 Replies
Correction
Posted Nov 4, 2008 06:09 PM by youssef.mohammed
1 Replies
Instead of synchronising getInstance
Posted Nov 3, 2008 05:42 AM by grahamkelly
1 Replies

Make a New Comment

You must log in in order to post a comment.

Related Resources

Dustin SullivanIf You Are New to Java Programming...
By Dustin SullivanJune 2, 2009 No Comments

We recently sat down with several top Java developers to talk about that state of the language as we approach this year's JavaOne.  As we were wrapping up, we threw one last question at them out of curiosity, and we thought you'd like to see what some of them said.

Steven HainesOracle Buys Sun of $7.4B
By Steven HainesApril 20, 2009 No Comments

In a stunning turn of events, Oracle steps in and buys Sun amist the breakdown of IBM's attempt to acquire Sun.

Steven HainesIBM in talks to buy Sun Microsystems for at least $6.5B
By Steven HainesMarch 18, 2009 No Comments

Reuters reported this morning that IBM is in talks to buy Sun Microsystems, which could "bolster their computer server products against rivals such as Hewlett-Packard Co."

See More Blogs

Informit Network