J2EE Blueprints Design Pattern
Data Access Object (DAO)

 name

Data Access Object (DAO)

 abstract

Creates flexible information resources by encapsulating and hiding their access mechanisms. Especially useful for encapsulating the SQL for Bean Managed Persistence. Decouples a resource class's usage from how it is represented internally or persistently.

 intent

Provide flexible, extensible access to data and other resources

 category

Object Structural

 motivation

Systems that rely on specific features of underlying resources, such as a particular vendor's database, tie together business logic and data access mechanisms. The result is often limited portability and undesirable vendor lock-in. As these underlying products become obsolete, or as superior solutions appear, systems tied to older versions of products can be difficult to upgrade or replatform. And enterprise bean component vendors want to avoid tying their business logic components to a particular vendor, so they can serve the broadest possible segment of the market.

The Data Access Object (or DAO) pattern separates the interface to a system resource from the underlying strategy used to access that resource. The Java Pet Store uses the DAO pattern both to achieve database vendor independence, and to represent XML data sources as objects.

Each enterprise Bean that accesses a back-end resource in the Java Pet Store application has an associated DAO class, which defines an abstract API of operations on the resource. This abstract API makes no reference to how the resource is implemented. The DAO simply has to know how to load itself from persistent store based on some identity information (a primary key, a filename, etc.), how to store itself, and so on. For example, an enterprise bean uses data it obtains from the DAO, not directly from the database. In this way, the enterprise bean defers its persistence mechanism to the DAO, allowing it to concentrate entirely on implementing business methods.

A Data Access Object class provides resource functionality for a particular resource, and implemented for a particular persistence mechanism. For example, the Java Pet Store uses the class CatalogDAO to encapsulate the database code that accesses both single and lists of Categories, Products and Items. The fact that CatalogDAO is implemented in terms of JDBC is hidden from the rest of the application. Reimplementing CatalogDAO for a different persistence mechanism (to use stateful entity beans, for example,) would have little or no impact on the classes that use CatalogDAO, since only the implementation, not the interface, would change. Each potential alternate implementation of CatalogDAO would access data for the items in the Catalog in its own way, while presenting the same API to the enterprise bean.

The DAO class is not limited to representing objects stored in a database. The Java Pet Store also uses the DAO pattern to represent XML data sources as objects. Instead of manipulating an in-memory representation of an XML document, the Java Pet Store represents the screen flow in the application as an instance of class ScreenFlowXmlDAO. If the designers (or maintainers) were to decide to change the application to store screen flow information in the database, instead of in an XML file, they would need only implement a single new class (ScreenFlowCloudscapeDAO, for example). The code that uses ScreenFlowXmlDao would remain unchanged, but the data would come from the database via the new class. Likewise, a new concrete subclass of OrderDAO (say, for example, OrderDAORemoteXml,) could access a remote XML data source to get the underlying data for instance of an OrderEJB.


 applicability

Use Data Access Object:

  • to separate resource interface from resource implementation
  • whenever the resource implementation mechanism might change
  • to support selecting resource implementation method at deploy time

 structure

Figure 1. UML Diagram for Data Access Object.

 participants

enterprise bean

  • abstracts business operations
  • avoids making reference to the external resources it uses
NonEJB

  • an arbitrary class may also access DAOs
DataAccessObject

  • abstracts operations on a resource
  • provides a standardized API for accessing and manipulating data of a particular type
Resource

  • provides resource data persistence and retrieval by way of an arbitrary API

 collaborations

enterprise bean

  • Uses a DataAccessObject for standardized, opaque access to a Resource
NonEJB

  • Can also use a DataAccessObject for standardized, opaque access to a Resource
DataAccessObject

  • provides an abstract API for the resource
  • provides the standard way for EJB's or NonEJB's to access and manipulate a particular type of Resource
Resource

  • provides data to ConcreteDataObject

 consequences

Potential consequences of using the Data Access Object pattern include:

  • Greater deployment flexibility. Data Access Objects present resources as DAOs. An Abstract Factory can use deployment configuration data to select a Data Access Object's class and initialization data at runtime, automatically configuring the application to use a particular database type.

    In fact, this is precisely how the OrderDAO class works in the Java Pet Store. The application code accesses Order data through the abstract class OrderDAO, implemented by a concrete subclass of OrderDAO (OrderDAOOracle, OrderDAOSybase, or OrderDAOCS). The application gets the OrderDAO by calling the public static method OrderDAOFactory.getDAO(), which constructs an appropriate OrderDAO subclass based on the database product name of the JDBC data source (as reported by JNDI).

  • Resource vendor independence. Coding business logic with vendor-specific APIs locks components into that vendor. The layer of indirection provided by the DAO pattern centralizes vendor-specific code in a class or several classes, where it can be replaced if necessary or desirable.

  • Resource implementation independence. The question of vendor lock-in aside, similar types of resources are often available in various formats through various access methods. For example, persistent data store can be implemented by a relational database, an object database, flat files in a filesystem, interaction with a remote persistence server, and so on. The DAO pattern allows the designer to focus on the behavior of application objects, and separate out data access mechanism details.

  • Easier migration to Container Managed Persistence. Data Access Object encapsulates persistence logic, separating it from Bean business logic, and facilitating migration from Bean Managed Persistence (BMP) to Container Managed Persistence (CMP). Furthermore, separate ConcreteDataObject classes can implement either BMP or CMP, which can be selected as appropriate to the implementation context. While reimplementation of the DAO classes will still be necessary, the code that needs are implementing will be encapsulated in one place.

  • Enhanced extensibility. New resource types are easy to add, requiring only a new ConcreteDataObject layer for the resource type, plus integration of that layer into the existing framework.

  • More classes and objects. The Data Access Object pattern adds a level of indirection to data access, increasing the number of classes and objects in the system and making the code slightly less clear. The memory impact of these additional classes and objects can be minimized by techniques such as caching, as well as avoiding redundant copies of data in the enterprise bean.


 implementation-issues

Here are some issues to consider when implementing the Data Access Object pattern:

  • Automatically generating the ConcreteDataObject layer facilitates maintenance, extensibility, evolvability and portability. Automatically-generated DAO layer code facilitates maintenance, primarily because generated code tends to have fewer flaws than handwritten code. In systems with large numbers of DAO classes, generation can be the only practical solution. Portability is enhanced across resource types as well as platforms, because resource type and platform-specific functionality can be written into the generation tool. This solution also enhances extensibility, since new functionality can be added to entire groups of DAO classes by modifying the code generation.

    When Data Access Object is used to abstract database resources, the greatest benefit is often evolvability. Database schema changes almost always have an impact on code. If the DAO layer is generated from the database schema, database schema changes can be reflected in code simply by regenerating. Of course, this does not address the question of adding or modifying the functionality the new schema is meant to support, but it does automate code changes (such as adding or deleting field accessors) which are totally derivable from schema. Functionality not derivable from database metadata can be implemented in subclasses of the DAO classes, to isolate the "custom" behavior from generated behavior.

    Software development organizations can develop a standardized, database DAO generation toolset, reusable across projects. Such a toolset, well-understood by its users, would encourage coding consistency across projects, while allowing selection of the most appropriate resource implementation for the project.

  • Consider introducing an abstract base class. If there are several potential implementations of the same DAO class, it may be useful to create an abstract DAO class, which those implementations then extend. Functionality common to the implementations can be implemented in the abstract base class, while implementation-specific code is placed in the concrete subclasses.

    The Java Pet Store uses this technique (as described above) for the OrderDAO class. OrderDAO is an abstract DAO class, which implements functionality common to all Order subclasses. The Order subclasses implement functionality exclusively related to a single database type. At runtime, the application selects the appropriate subclass of OrderDAO to access the configured database.

  • An abstract DAO class does not necessarily imply a least common denominator solution. While it is true that abstraction may impede efficiency by hiding implementation details that might otherwise be used for optimization, it's usually possible to design around a "least common denominator" limitation. An optimization that is inaccessible from the abstract DAO layer can usually be made accessible by moving the functionality into the DAO API. DAO subclasses that cannot perform the optimization can either simulate the operation (possibly suboptimally), or treat to request as an error condition which the caller must then handle.

  • Data Access Objects can be accessed by both EJBs and objects of arbitrary class. While DAO classes are useful abstractions for implementing EJBs in a database-independent way, they can also be used by any class to access resources. For example, the Java Pet Store Catalog class accesses DAOs directly from the application's web tier of the application, and the application screen flow comes from a DAO that is backed by an XML file.

  • Consider making the DAO an interface. If none of the operations on a DAO have meaningful default implementations, a DAO may be defined more flexibly as an interface instead of as a concrete class or abstract base class. When using an interface, default implementations of an DAO interface can be reside in a "support" class, which is a DAO whose methods implement the interface, but either do nothing, or have some reasonable default behavior. Programmers subclass the support class, overridding only those methods necessary to implement the desired functionality.

  • The Data Access Object pattern might complicate transactional logic.Different resource implementations may have very different transactional behaviors. As a result, it may be difficult to decide where (in an abstract API) to put the logic for transactional operations on the underlying resource. One possible solution to this problem might be introduce an opaque "helper" class, which encapsulates information the DAO class needs to perform its transactional functions. This class will encapsulate transaction state in a way comprehensible to the DAO class.

  • Container Managed Persistence may make Data Access Object unnecessary. Container Managed Persistence already abstracts the data persistence mechanism out of the enterprise bean logic, making DAO superfluous.


 sample-code

An example of Data Access Object using an Abstract Factory to select an underlying database resource: OrderDAOFactory.java OrderDAO.java OrderDAOCS.java OrderDAOOracle.java OrderDAOSybase.java

An example of a concrete Data Access Object representing an underlying, non-database resource (an XML file): ScreenFlowXmlDAO.java


 related-patterns

Strategy (GoF)
Policy
Adapter (GoF)
Wrapper