`
guanhuaing
  • 浏览: 1199355 次
文章分类
社区版块
存档分类
最新评论

IbatisNet源码解读 - DataMapper

 
阅读更多

http://www.fanxiao.com/Blogs/jishu/200807/20080725002740.Html

DataMapper IbatisNet的核心,也是最复杂的部分。

关于的工作原理或者说Ibatis的架构的简单描述如图所示:。

.主要接口

1. IPreparedCommand 接口

IPreparedCommand接口 位于IBatisNet.DataMapper.Commands

定义了void Create (RequestScope request, IDalSession session, IStatement statement, object parameterObject )协议,实现类将为IDalSession和当前的IStatement生成一个IDbCommand并填充适当的参数对象,然后放入RequestScope中。

2. ISql 接口

ISql接口 位于IBatisNet.DataMapper.Configuration.Sql

提供了RequestScope GetRequestScope(object parameterObject, IDalSession session)协议,实现类将为当前的会话请求获取RequestScope,并且为DynamicSql/SimpleDynamicSql填充parameterObjectRequestScope代表一个请求范围内的所有的和mapped statement处理相关的数据,比如要执行的IDbCommand,当前的ResultMapParameterMap等。

3. ITypeHandler接口

ITypeHandler接口 主要用于在结果集和实际类型之间处理和转换。

4. IMappedStatement接口

IMappedStatement接口 定义了一个MappedStatement的行为。包括ExecuteInsertExecuteUpdateExecuteQuery等。

5. IStatement接口

IStatement接口封装了Ibatis DataMap模型中的一个可执行的sql语句相关的属性,比如CacheModelNameParameterClassResultMapSql等。

6. ISqlChild接口

ISqlChild接口是一个标志接口。代表Sql的子元素。

.关键类

1.Commands目录

主要用于创建PreparedCommand包括DefaultPreparedCommandEmbedParamsPreparedCommand

2.Configuration目录

维护Ibatisxml配置文件和对象模型的映射,是SqlMap的模型层。

3.Exceptions目录

包含一个DataMapperException 类,DataMapper模块运行过程产生的所有异常都被转换为DataMapperException异常。

4.MappedStatements目录

该目录包含了MappedStatement的核心执行类。

5.Scope目录

维护了配置,请求和错误相关信息的范围类。ConfigurationScope类维护了配置文件处理过程的状态;ErrorContext用于为创建有确切含义的错误信息维护状态;RequestScope保持整个MappedStatement的执行状态和信息。

6.TypeHandlers目录

处理数据库类型和DotNet类型的转换。

7.主目录

SqlMapSession 实现了 IDalSession,用于维护与SqlMap相关的数据访问层的会话信息。

SqlMapper 一个Facade类,通过MappedStatement执行相应的数据库操作。

Mapper 用于访问通过SqlMap.Config定义的缺省SqlMapper的单例类。

.执行流程

使用IbatisSqlMapper比较简单,最简单的一般需要四步:

1.提供SqlMap.config配置文件,用于定义相关的数据源和sql映射。xml

2.提供SqlMap的配置文件,定义sql映射。xml

3.写相关的业务类,用于查询结果的映射,如果不需要查询,有时可以省略该步。bll

4.调用框架执行。

一个简单的例子:

SqlMap.config配置文件--

SqlMap.config

-----------------------------------------------------------------------------------

<?xml version="1.0" encoding="utf-8"?>

<sqlMapConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="SqlMapConfig.xsd">

<settings>

<setting useStatementNamespaces="false"/>

<setting cacheModelsEnabled="true"/>

</settings>

<providers>

<provider

name="oracle9.2"

description="Oracle, Oracle provider V9.2.0.401"

enabled="false"

assemblyName="Oracle.DataAccess, Version=9.2.0.401, Culture=neutral, PublicKeyToken=89b483f429c47342"

connectionClass="Oracle.DataAccess.Client.OracleConnection"

commandClass="Oracle.DataAccess.Client.OracleCommand"

parameterClass="Oracle.DataAccess.Client.OracleParameter"

parameterDbTypeClass="Oracle.DataAccess.Client.OracleDbType"

parameterDbTypeProperty="OracleDbType"

dataAdapterClass="Oracle.DataAccess.Client.OracleDataAdapter"

commandBuilderClass="Oracle.DataAccess.Client.OracleCommandBuilder"

usePositionalParameters = "false"

useParameterPrefixInSql = "true"

useParameterPrefixInParameter = "false"

parameterPrefix=":"

useDeriveParameters="false"

/>

</providers>

<database>

<provider name="oracle9.2"/>

<dataSource name="ibatisDemo" connectionString="Data Source=DATA-89;Persist Security Info=True;User ID=data;password=data"/>

</database>

<sqlMaps>

<sqlMap resource="product.xml"/>

</sqlMaps>

</sqlMapConfig>

-----------------------------------------------------------------------------------

SqlMap的配置文件--

product.xml

-----------------------------------------------------------------------------------

<?xml version="1.0" encoding="UTF-8" ?>

<sqlMap namespace="Product" xmlns="http://ibatis.apache.org/mapping"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<alias>

<typeAlias alias="Product" assembly="Product.dll" type="Domain.Product" />

</alias>

<resultMaps>

<resultMap id="productResult" class="Product">

<result property="Id" column="ID"/>

<result property="PlatId" column="PLAT_ID"/>

<result property="Org" column="create_org"/>

</resultMap>

</resultMaps>

<!-- =============================================

MAPPED STATEMENTS

=============================================

-->

<statements>

<select id="getProduct" parameterClass="Product",resultMap="productResult">

select

ID, PLAT_ID,CREATE_ORG

from PRODUCT_TEMP

where ID = #Id#

</select>

<update id="updateNews" parameterClass="Product">

update PRODUCT_TEMP

set create_org=#Org#

where ID = #Id#

</update>

</statements>

</sqlMap>

-----------------------------------------------------------------------------------

业务类--

product.cs

-----------------------------------------------------------------------------------

using System;

using System.Collections.Generic;

using System.Text;

namespace Domain

{

public class Product

{

private string _id, _platId, _org;

public string Id

{

get { return _id; }

set { _id = value; }

}

public string Org

{

get { return _org; }

set { _org = value; }

}

public string PlatId

{

get { return _platId; }

set { _platId = value; }

}

}

}

-----------------------------------------------------------------------------------

调用SqlMap执行

-----------------------------------------------------------------------------------

class Program

{

public static void Main(string[] args)

{

//ISqlMapper mapper = Mapper.Instance();//初始化实例

//由于我们定义的sqlmap映射文件中的getProduct查询需要Product实例作为参数,并且使用ProductId

//首先实例化一个Product并设置其Id

Product p=new Product();

p.Id = "FR20T0000003000000096426";

//调用SqlMapperQueryForObject方法通过在sqlmap中的getProductsql语句,查询数据库,并将结果集映射为Product对象

p = (Product)Mapper.Instance().QueryForObject("getProduct", p);

Console.WriteLine("{0}-{1}-{2}",p.Id, p.Org, p.PlatId);

//修改Org属性

p.Org = "orgid2";

//通过updateNews sql,传入具体的Product实例,更新数据库。

Mapper.Instance().Update("updateNews", p);

//再次查询

Product p1 = (Product)Mapper.Instance().QueryForObject("getProduct", p);

Console.WriteLine("{0}-{1}-{2}", p1.Id, p1.Org, p1.PlatId);

}

}

-----------------------------------------------------------------------------------

以上就是一个简单的实例,下面根据源代码简介其执行流程。

Mapper.Instance()时,

如果默认SqlMap已初始化则直接返回初始化的实例,如果没有初始化则通过DomSqlMapBuilder从配置文件中初始化SqlMap

DomSqlMapBuilder主要通过xpathxml配置文件映射为Ibatis DataMap模型。

也就是说SqlMap.config文件的xml元素和DataMap的对象模型是对应的。

处理SqlMap.config的过程中会处理sqlmap.config中,我们定义的映射文件,例如例中的product.xml

<sqlMaps>

<sqlMap resource="product.xml"/>

</sqlMaps>

SqlMapper构造成功后,下一步就是执行具体的在我们自己的sqlMap文件(product.xml)中定义的sql映射

例如public object QueryForObject(string statementName, object parameterObject)

该方法首先会按照statementName获取在解析product.xml文件过程中生成的MappedStatement实例,

我们的例子中就是getProduct对应的select语句:

<select id="getProduct" parameterClass="Product",resultMap="productResult">

select

ID, PLAT_ID,CREATE_ORG

from PRODUCT_TEMP

where ID = #Id#

</select>

这个语句需要一个Product类型的参数,结果是一个resultMap--productResult,定义如下:

<resultMap id="productResult" class="Product">

<result property="Id" column="ID"/>

<result property="PlatId" column="PLAT_ID"/>

<result property="Org" column="create_org"/>

</resultMap>

执行时,框架首先会获取当前的IDalSession,然后代理给具体的MappedStatement实例进行数据库操作,

比如SelectMappedStatement

处理得过程首先会根据不同的语句类型(insertselect),和相关配置信息(参数类型,结果类型,sql语句本身等)进行参数邦定,

然后通过ado.net进行数据库访问,如果需要返回结果,自动组装结果等过程,

然后返回。执行的过程中还会有缓存管理异常处理事件触发和管理等,使用者可以不用了解细节

总结:

可以看出,IbatisSqlMapper使用还是相对简单的,

要充分使用IbatisSqlMapper,最主要的是要掌握它的模型和配置,模型和配置是对应的。不掌握模型很难很好的编写配置文件。

有时间会按专题介绍Ibatis配置中的重要模型。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics