The Data Access Object pattern in the Core J2EE Pattern Catalog suggests that while creating a robust J2EE application, you should abstract and encapsulate all access to a data source behind a common API. In terms of programming, what this means is to create an interface defining all of the business methods that your application needs. Inside your application, you use this interface when you want to interact with your data store, and then create a separate class that implements this interface and has the logic for interacting with that particular data store.
For example, consider the sample application developed in the article iBatis: SQL Maps. This is a Struts application that allows you to fire SELECT
, INSERT
, UPDATE
and DELETE
SQL queries on a CONTACT
table. In this application, we are using SQL Maps as the persistence framework. Now say we want to change this application so that the CONTACT
table is stored in an XML file instead of a RDBMS, or want to use Hibernate for SELECT
queries and SQL Map for the other three queries, perhaps because Hibernate provides better support for caching. This will be very hard to implement, and if we are able to change it at all, it won't be a very clean solution.
A better approach for this type of problem would be to create a ContactDAO
interface and define business methods for SELECT
, INSERT
, UPDATE
, and DELETE
queries in this interface. Then you'd create separate classes containing persistence logic for each method. So there would be a class that knows how to interact with the CONTACT
table using SQL Maps, another class that knows how to interact with the CONTACT
table if it is stored in a XML file instead of a RDBMS, and so on. Inside your application, you'd choose from different implementations of ContactDAO
, depending on your requirements. This relationship is shown in Figure 1.
Figure 1. ContactDAO
interface and implementations
Related Reading ![]() J2EE Design Patterns |
iBatis Data Access Object (DAO) is an open source framework now hosted by Apache and targeted at solving these type of problems. It provides you with an infrastructure for creating applications based on the DAO pattern. What this means is that you can create a XML file and declare that XMLContactDAO.java is the implementation class for ContactDAO
, which knows how to read and write contacts in an XML file instead of a RDBMS. SQLMapContactDAO
is an implementation class that knows how to interact with the CONTACT
table using SQL Maps as its persistence framework. Inside your application, you ask the DAO framework for an implementation of ContactDAO
for XML, and it will provide you with an XMLContactDAO
object. Also, the DAO framework provides you with a uniform interface to handle transaction management, irrespective of what persistence mechanism you use. It will also take care of the low-level details of connection management and initializing persistence frameworks.
This article is a step-by-step guide on how to use the iBatis DAO framework in your application. We will start by looking at how to change our sample application developed in the SQL Maps article to use the DAO framework. Then we will talk about the architecture of the DAO framework. Next we will look at which transaction managers are supported in DAO framework, and will finish with a section on how to create your own transaction manager.
Sample Application
We will start by changing our sample application developed in the SQL Maps article to use the DAO framework.
-
Copy the ibatis-dao-2.jar file to your WEB-INF/lib folder.
-
Create DAOMap.xml at the root of your JavaSource folder, like this:
<daoConfig> <context id="sqlmap"> <transactionManager type="SQLMAP"> <property name="SqlMapConfigResource" value= "com/sample/contact/dao/sqlmap/SqlMapConfig.xml"/> </transactionManager> <dao interface="com.sample.contact.dao.ContactDAO" implementation= "com.sample.contact.dao.sqlmap.SQLMapContactDAO"/> </context> </daoConfig>
DAOMap.xml file is a deployment descriptor for your iBatis DAO framework.
<daoConfig>
is the root element. Each<context>
element represents one persistence mechanism. In our example, we will use only SQL Maps for persistence, so we so have only one<context>
element. Every persistence mechanism should have one<transactionManager>
element, which represents the manager used for getting a connection to the underlying data store and marking the transaction boundary. We will talk more abouttransactionManager
later.The
<context>
element also contains a list of DAOs for the given particular persistence mechanism. In our example, we want to create aContactDAO
, which will use SQL Maps for persistence, so we will add one<dao>
element definingSQLMapContactDAO
.