The Architecture of the DAO Framework
Since we now have a working application, thanks to the DAO framework, let's take a peek at what is going on under the hood. First take a look Figure 2, a sequence diagram of how DAO works.
Figure 2. DAO sequence diagram (click for full-size version)
To initialize the DAO framework, you start by calling DaoManagerBuilder.buildDaoManager()
and passing the DAOMap.xml file to it. In this method, the DAO framework will read DAOMap.xml and create a corresponding DAOManager
object from it. This object will contain data representing the supported persistence mechanisms. Which interfaces are implemented, and what's the implementation class for a particular combination of interface and persistence mechanism? Basically, this is the Java object equivalent of the DAOMap.xml file.
Once you have a DAOManager
object, you can query it to get the SQL Map implementation of the ContactDAO
interface. The DAO framework will return a DaoProxy
object that wraps the implementation class. In our example, it will return a DaoProxy
object for the SQLMapContactDAO
class. The DaoProxy
object allows the DAO framework to intercept calls to business methods. In our example, when you call contactDAO.selectContact()
, the DAO framework will intercept the call and check whether the transaction is already started. If not, it will start a new transaction call by calling the startTransaction()
method on the transaction manager. Once the transaction is started, it will call the selectContact()
method of SQLMapContactDAO
within that transaction. The DaoProxy
object will intercept the call to selectContact()
method on its way back and use it for committing the transaction.
By the way, if you don't want your transaction to be scoped on the method level, or if you want to call multiple methods in one transaction, you can call daoManager.startTransaction()
before calling a business method on ContactDAO
, and commit that transaction when done by calling daoManager.commitTransaction()
.
Now the only remaining issue is who takes care of initializing the persistence mechanism and passing control to it. In our example, that means deciding who passes the path of SqlMapConfig.xml to the SQL Map framework and initializes it. This also means deciding who takes care of the actual interaction with the SQL Maps framework. The DAO framework provides us with Template
classes for every persistence mechanism. In your application, you should extend your implementation class from this Template
class, and write only business logic in your method; after that, pass control to this template class, which will take care of interacting with persistence mechanism. Our example calls super.queryForObject("getContact",new Integer(contactId));
, which means SqlMapDaoTemplate
will take care of initializing and interacting with the SQL Maps framework.
Your persistence mechanism may need some information for initialization. In our example, it requires the path to SqlMapConfig.xml, which contains information like the name of the driver class, the JDBC URL, the login info, etc. Such information required by a particular transaction manager is passed as a property element to it in the DaoMap.xml file. In the next section, we will talk about which transaction managers are supported by the DAO framework and the initialization information required by each.
Supported Persistence Mechanisms
The DAO framework provides built-in support for a few persistence mechanisms. To use one of the built-in transactionManager
s, you have to do two things:
- Declare support for it in DAOMap.xml file by adding a
<transactionManager>
element and passing required information to it as properties. - Extend the appropriate
Template
class for thattransactionManager
while creating your DAO implementation class.
Now we will go through the built-in transactionManager
s and find out how to use each of them in your application.
JDBC
The JDBC transaction manager is good if you don't want to use any framework for persistence and want to write your own JDBC code. If you're using JDBC as your persistence mechanism, you can use one of the three connection management options:
SIMPLE
: UseSIMPLE
as the value of theDataSource
element if you want to use iBatis' own implementation of connection pooling. Pass the usual JDBC properties (DriverManager
class, JDBC URL, etc.) to it asProperties
. Look at the online iBatis documentation to learn about advanced connection properties.<transactionManager type="JDBC"> <property name="DataSource" value="SIMPLE"/> <property name="JDBC.Driver" value="com.ibm.db2j.jdbc.DB2jDriver"/> <property name="JDBC.ConnectionURL" value="jdbc:db2j:D:/cloudscape/wpsdb"/> <property name="JDBC.Username" value="db2admin"/> <property name="JDBC.Password" value="db2admin"/> <property name="JDBC.DefaultAutoCommit" value="true" /> </transactionManager>