IBatis—源码解析【DataAccess】

   DataAccess是一个DAO框架,可以通过配置文件配置应用程序使用的DAO实现,并且自己提供了几个具体数据访问方式的包装,以简化DAO实现层开发。
   DataAccess的源代码相对于DataMapper要简单的多。
一.关键类
1.Configuration目录
   定义了DataAccess的模型,该模型和xml配置文件对应,因此该目录同时提供了从xml配置文件解析为DataAccess对象模型和将对象模型序列化为xml文件的功能。
2.Exceptions目录
   Exceptions目录中只有一个DataAccessException异常类。DataAccess框架产生的异常会被包装为该类。
3.Interfaces目录
  Interfaces目录定义了两个接口:IDao和IDaoSessionHandler。IDao是我们自己的DAO实现类必须继承的标志接口。IDaoSessionHandler定义了不同会话处理器(SessionHandler)的通用接口。用于从配置Dao管理器相关的信息,并获取当前的DaoSession。
4.Scope目录
   维护当前的配置和错误信息。
5.DaoSessionHandlers目录
   DaoSessionHandlers目录包含对ADO.NET和SqlMap的包装。比如SimpleDaoSession 是 An ADO.NET implementation of the DataAccess Session .SqlMapDaoSession 是 An SqlMappper implementation of the DataAccess Session.这两个类都实现了IDaoSession,用来处理会话相关的连接,事务等。SimpleDaoSessionHandler和SqlMapDaoSessionHandler类都实现了IDaoSessionHandler接口,用于从解析后的配置信息中获取DaoSession和其相关的配置。
6.主目录
   SessionHolder类和java中的ThreadLocal类似,为每个线程维护一个IDalSession。
DaoManager是一个Facade类,复杂读取配置文件并初始化框架;为不同的context维护不同的配置信息;提供访问DAO实现的方法;提供访问当前Session中的连接(connection)和事务(transaction)方法。

二.使用简介和框架执行流程
DataAccess框架(图略):
由于DataAccess可以和任何DAO实现工作,核心库中提供了对ADO.NET和SqlMap(也就是DataMapper)的封装,扩展库中提供了对NHibernate的封装,利用这些封装编成很更简单,更实用。DataAccess文档上说:
if your application is using raw ADO, the DAO framework will hide classes like DataReader, DataAdapter, Connection, and Command. Similarly, if your application is using the NHibernate object persistence library, the DAO framework will hide classes like Configuration, SessionFactory, Session, and HibernateException. All of these implementation details will be hidden behind a consistent DAO interface layer. Furthermore, the number of different data sources that are being used can be hidden from the view of the application.
这里只简单介绍DataAccess和DataMapper配合使用,DataMapper的类和配置利用以上介绍的DataMapper中的例子。
DataAccess的使用需要以下几个步骤:
1.设计DAO接口。
2.选择一种DAO实现。
3.编写dao.config配置文件。
4.利用DAO进行数据操作。
由于DataAccess框架要求每个DAO实现类,必须实现IDao接口,即然利用DAO框架编程,我们必须定义自己的DAO接口。作为最佳实践可以这样设计:
1).我们自己的DAO接口应该是和任何框架无关的,也就是我们的DAO接口不需要继承自IDao接口,而且所有的DAO接口在一个或几个项目中,最后打包为一个或几个dll中,例如:
namespace dao
{
public interface IProduct
{
IList GetProductList();
void UpdateProduct(Product pro);
}
}
2).设计一个BaseDao基类,该类封装了一种具体的DAO实现的数据访问方法并且实现IDao标志接口,例如我们利用SqlMapper作为数据持久层,BaseDao可以这样设计:
namespace impl
{
public class BaseDao : IDao
{
protected const int PAGE_SIZE = 4;
///
/// Looks up the parent DaoManager, gets the local transaction
/// (which should be a SqlMapDaoTransaction) and returns the
/// SqlMap associated with this DAO.
///
/// The SqlMap instance for this DAO.
protected SqlMapper GetLocalSqlMap()
{
DomDaoManagerBuilder builder = new DomDaoManagerBuilder();
builder.Configure();
DaoManager daoManager = DaoManager.GetInstance(this);
SqlMapDaoSession sqlMapDaoSession = (SqlMapDaoSession)daoManager.LocalDaoSession;
return sqlMapDaoSession.SqlMap;
}
///
/// Simple convenience method to wrap the SqlMap method of the same name.
/// Wraps the exception with a DataAccessException to isolate the SqlMap framework.
///
protected IList ExecuteQueryForList(string statementName, object parameterObject)
{
SqlMapper sqlMap = GetLocalSqlMap();
try
{
return sqlMap.QueryForList(statementName, parameterObject);
}
catch (Exception e)
{
throw new DataAccessException("Error executing query '" + statementName + "' for list. Cause: " + e.Message, e);
}

/// Simple convenience method to wrap the SqlMap method of the same name.
/// Wraps the exception with a DataAccessException to isolate the SqlMap framework.
///
protected IList ExecuteQueryForList(string statementName, object parameterObject, int skipResults, int maxResults)
{
SqlMapper sqlMap = GetLocalSqlMap();
try
{
return sqlMap.QueryForList(statementName, parameterObject, skipResults, maxResults);
}
catch (Exception e)
{
throw new DataAccessException("Error executing query '" + statementName + "' for list. Cause: " + e.Message, e);
}
}
...................
}
}
3).我们的具体DAO实现类继承自BaseDao,并实现自己的DAO接口。并利用BaseDao提供的基础功能工作,而且所有的DAO实现在一个或几个项目中,最后打包为一个或几个dll中,这样以后可以简化维护并方便修改daofactory的配置,例如:
namespace impl
{
public class ProductDAO : BaseDao, IProduct
{
#region IProduct Members
public IList GetTheProductList()
{
IList prods = base.ExecuteQueryForList("getProduct", null);
Console.WriteLine("public System.Collections.IList GetProductList():");
foreach (Product p in prods)
{
Console.WriteLine("id:{0};Org:{1};PlatId:{2}", p.Id, p.Org, p.PlatId);
}
return prods;
}
public void UpdateTheProduct(Product pro)
{
base.ExecuteUpdate("updateNews", pro);
Console.WriteLine("public void UpdateProduct(Domain.Product pro) finished.");
}
#endregion
}
}
配置文件--dao.config
xml version="1.0" encoding="utf-8"?>
<daoConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<providers resource="providers.config"/>
<context id="SqlMapDao" default="true">
<database>
<provider name="oracle9.2"/>
<dataSource name="ibatisDemo" connectionString="Data Source=DATA-89;Persist Security Info=True;User ID=data;password=data"/>
database>
<daoSessionHandlers>
<daoSessionHandler id="SqlMap">
<property name="resource" value="sqlMap.config"/>
daoSessionHandler>
daoSessionHandlers>
<daoFactory>
<dao interface="dao.IProduct,dao" implementation="impl.ProductDAO,impl"/>
daoFactory>
context>
daoConfig>
使用DAO实现操作数据存储
namespace OraTest
{
class Program
{
public static void Main()
{
public static void Main()
{
//读取配置文件创建DaoManager,并获取SqlMapDao context实例。
DomDaoManagerBuilder builder = new DomDaoManagerBuilder();
builder.Configure();
DaoManager daoManager = DaoManager.GetInstance("SqlMapDao");
//获取IProductDAO接口的具体实现类,并初始化。
IProduct dao = daoManager[typeof(IProduct)] as IProduct;
//利用DAO编程。
dao.GetProductList();
Product p = new Product();
p.Id = "FR20T0000003000000096426";
p.Org = "orgid2";
dao.UpdateProduct(p);
}
}
}

posted on 2009-06-08 15:37  一江秋水  阅读(495)  评论(0编辑  收藏  举报