MyBatisiBatis –> MyBatis

从今 Clinton Begin 到 Google(从 iBatis 到 MyBatis,从 Apache Software
Foundation 到 Google Code),Apache 开源代码项目,O/R Mapping
解决方案,基于 SQL 映射(将SQL语句映射为Java/.Net对象)的支持 Java 和
.Net 的数据看工具与持久层框架。

MyBatis 1

iBatis
作为一个映射层,在目标(类-字段)和数据库(数据表-列)之间传递数据,并保持双方与映射层的互独立,低耦合。

  • 小巧简单、轻量级,快速开,提供满足要求、灵活简单的缓解方案
  • iBATIS 提供单身于数据库的接口和 API
  • 支撑存储过程、内嵌的 SQL、动态 SQL
  • SQL语句以单独的 XML 文件中,与程序代码分离,可移植性
  • SQL 语句需要手动灵活配置,半自动化(相比全自动化的Hibernate)

iBatis 提供的持久层框架包括 SQL
Maps 和 Data Access
Objects(DAO),同时提供一个运用该框架开发的 JPetStore 实例。

  • SQL Maps:整个iBatis Database
    Layer的中心价值,通过XML文件贯彻由实体到SQL语句的照射,显著节约数据库操作的代码量
  • DAO:提供接口操作数据,隐藏实现细节

iBatis 运行方式接近
ADO.Net,连接数据库、设置参数、执行语句、获取并返回结果、关闭并释放资源。

关于 ADO.Net

精益求精之ADO数据访问模型,Microsoft
提供的一模一样组用于和数据源进行互的面向对象类库,.NET
编程环境面临先行利用的数量看接口。

  • 内存表示:DataSet 对象
  • 数看:DataTable 的 Rows 集合 索引访问

连锁信息可参见:ADO.Net
入帮派上;

脚直接被出 iBatis 的框架结构

MyBatis 2

有关 iBatis 的现实信息参见官网:iBatis –>
MyBatis;MyBatis for
.Net; MyBatis for
Java;

SqlMapXxxx.config

iBatis SqlMap 配置文件(DataMapper 配置文件),类似项目之 web.config 或 app.config

  • 点名 MyXxxx.xml 和 providers.config 文件之岗位
  • 概念 DataMapper 的另外安排选

SQL Map
将目标持久化至关系项目数据库,方便维护(无需修改代码,只需要动态维护XML文件即可)

当路面临,推荐一个数据源(数据库)对应一个
SqlMapXxxx.config 文件 和 一个 providers.config
文件

  • DB2:SqlMapDB2.config、providersDB2.config
  • SQLServer:SqlMapSQLServer.config、providersSQLServer.config

SqlMapXxxx.config
用于将 MyXxxx.xml 文件载入到 iBatis
框架。

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

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

    // 自增长属性等配置信息
    <propertys>
       <property />
    </propertys>

    // 配置信息
    <settings>
       <setting />
    </settings>

    // 数据库相关信息
    <providers resource="bin/DBConfig/iBatis/providersDB2.config"/>  
    <database>
       <provider name="iDb2.9"/>  
       <dataSource name="SourceName" connectionString="Database=xxx;User ID=xxx; Password = xxx;"/>
    </database>

    // SQL映射信息文件
    <sqlMaps>
       <sqlMap resource="bin/DBConfig/SqlMap/MyXxxx.xml" />
    </sqlMaps>

</sqlMapConfig>

第一在拖欠配置中,凡是引用外部文件,均只是经过

  • resource:推荐,从类型的根本目录加载
  • url:从文本的绝对路径加载
  • embedded:作为序集的资源文件加载

配备信息 <setting /> 有关参数解释如下:

maxRequests:同时执行SQL语句的最大线程数
maxSessions:同一时间内活动的最大session数
maxTransactions:同时进入SqlMapClient.startTransaction()的最大线程数 
cacheModelsEnabled:全局性启用/禁用SqlMapClient的所有缓存model 
lazyLoadingEnabled:全局性启用/禁用SqlMapClient的所有延迟加载 
enhancementEnabled:全局性启用/禁用运行时字节码增强,优化访问JavaBean属性的性能,同时优化延迟加载性能 
useStatementNamespaces:如果启用本属性,必须使用全限定名来引用mapped statement。
                        Mapped statement的全限定名由sql-map的名称和mapped-statement的名称合成 

部署信息 <sqlMaps>  + <sqlMap> 指向 SQL 映射文件。

除此以外,上述消息引用 DB2 数据库,如果是援引 SQLServer 数据库,配置信息如下

<providers resource="bin/DBConfig/IBatis/providersSQLServer.config"/>
<database>
   <provider name="sqlServer2.0"/>
   <dataSource name="SourceName" connectionString="Data Source=IP;Initial Catalog=dbName;User ID=xxx;Password=xxx;connection reset=false;"/>
</database>

当朝在由增长列的表插入数据时,需要安排如下属性

// for SQLServer
<properties>
    <property key="selectKeyForXxxx" value="select @@IDENTITY as value" />
</properties>
// for SQLServer (推荐)
<properties>
    <property key="selectKeyForXxxx" value="select SCOPE_IDENTITY() as value" />
</properties>

// for DB2
<properties>
    <property key="selectKeyForXxxx" value="VALUES IDENTITY_VAL_LOCAL()" />
</properties>

关于 SCOPE_IDENTITY() 和 @@IDENTITY
的区别,参见:http://www.cnblogs.com/MingDe/archive/2011/10/12/2208749.html

于 MyXxxx.xml 文件被利用形式如下

<insert id="insertUser" parameterClass="User">   
   insert into Users values(null,#userName# ,#password#,#userType#);
     <selectKey resultClass="int" keyProperty="uid">
        ${selectKeyForXxxx}
     </selectKey> 
</insert> 

欠配置为可以一直当 MyXxxx.xml 文件之 <insert> 标签中配置。

<insert id="insertUser" parameterClass="User">   
   insert into Users values(null,#userName# ,#password#,#userType#);
     <selectKey resultClass="int" keyProperty="uid">
        SELECT @@IDENTITY AS uid  // uid是数据库表列名
     </selectKey> 
</insert>  

MyXxxx.xml

SQL 语句映射文件,iBatis 通过该 XML 文件来照 SQL
语句之输入和出口及讲话本身。

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

<sqlMap namespace = "与文件同名即可"
     xmlns="http://ibatis.apache.org/mapping" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >

  <!--别名设置-->
  <alias>
    <typeAlias alias="别名" type="命名空间.类名, 命名空间"/>
  </alias>

  <!--返回值配置-->
  <resultMaps>    
     <resultMap id="resultMapID" class="别名">  
       <result property="Param1" column="数据库列1" /> 
       <result property="Param2" column="数据库列2" /> 
     </resultMap> 
  </resultMaps> 


  <!--动态SQL配置-->
  <statements>
    <!-- SQL公用片段, 用于组装SQL语句 -->
    <sql id="sql_select_count">
        select count(*) 
    </sql>
    <sql id="sql_select_all">
        select * 
    </sql>
    <sql id ="sql_operation_where">
        from ( tableName or (select语句)
                where 
        <dynamic>
            动态组装 where 条件
        </dynamic>
    </sql>

    // 增删改查(Insert/Delete/Update/Select), 根据需要自行组装SQL语句
    <!-- Select -->
    <select id="selectID" parameterClass="别名" resultClass="resultMapID or 特定返回值类型" remapResults="true">     
          <include refid="sql_select_all"/>
          <include refid="sql_operation_where"/>
        )temp 
      where 条件
    </select> 
    <!-- Insert -->
    <insert id="insertID" parameterClass="别名">
        SQL语句 or 存储过程
    </insert>
    <!-- Update -->
    <update id="updateID" parameterClass="别名">
        SQL语句 or 存储过程
    </update>
    <!-- Delete -->
    <delete id="deleteID" parameterClass="别名">
        SQL语句 or 存储过程
    </delete>
  </statements>
</sqlMap>

下对投文件被的几乎独根本标签作讲

[0].
sqlMap

SQL 映射文件之根结点。因为 iBatis
运行时会拿装有映射文件一次性加载,所以属性 namespace
命名空间要唯一标识映射文件 。

同等命名空间下,标签的 id 属性不克重。若不同命名空间下是同样的签
id,需要利用 命名空间.标签id 访问。

[1].
resultMaps + resultMap

返回值配置,iBatis 映射文件中极其要害最精锐的要素。

[2].
alias + typeAlias

号配置,化繁为简,简短的号代替了限定的类名。

[3].
statements

动态SQL配置。动态SQL作为iBatis的雄强力量,灵活的动态SQL标签、提高SQL语句之重用性。

  • <sql>:SQL公用片段,可以用来组装SQL语句
  • <select> <insert> <update>
    <delete>
    :增删改查标签,可以行使 <sql> 自行组装SQL语句

[4].
<![CDATA[
xxxxxx ]]>

通过 <![CDATA[……]]>
节点,可以避免SQL中与XML规范相冲突的字符对XML映射文件之合法性造成影响。

The most common conflict between SQL and XML is the greater-than and
less-than symbols (><).

关于 <![CDATA[ … ]]>
的运,对于无数据库字段,应采用该标签包装。

[5]. parameterClass +
resultClass

parameterClass 代表输入参数类型完整类名,resultClass
表示回去结果类型完整类名,两者皆只是通过 alias 简化。

囤过程采用 parameterMap,除存储过程外的别样 <statement>
内的标签都采用 parameterClass 和 resultClass 配置方式。

style=”font-size: 15px;”>动态SQL

每当使用 <sql> 标签组装增删改查标签时,动态条件写于
<dynamic>、一首批标签、二首位标签 和 <iterator>
中,该标签可以放在

  • select 列表
  • where 过滤条件

蒙,下面详细介绍如何拼接动态 SQL 语句以及当小心的题目。

a)关于直接执行 SQL
语句,务必注意以下几点

1). 属性 remapResults="true" 配置
2). 推荐使用 $sql$ or <![CDATA[ $sql$ ]]> ,但是不要用 #sql#

b)插入类型的贮存过程,推荐以囤过程的结尾加加

// 返回最新主键
SELECT @@IDENTITY AS value

C)关于验证 where 和 AND/OR
在动态SQL中之职务问题

 

脚给出 IBatis 调用 SQL
语句的几乎单简易例子

[1]. 根据 ID 查询 Name

<select id="selectNameByID" parameterClass="int" resultClass="string">
    select name from dbo.StudentInfo where id=#id#
</select>

然后被出调用方式

int id = 101;
string statement = "MyXxxx.selectNameByID";
string stuName = DataOperationHelper.CallSql<string>(statement, id);

下面的代码,封装了2只措施,分别用于实施SQL语句和存储过程

MyBatis 3MyBatis 4

 1 /// <summary>
 2 /// 调用SQL
 3 /// </summary>
 4 /// <typeparam name="T"></typeparam>
 5 /// <param name="statement"></param>
 6 /// <param name="inParam"></param>
 7 /// <returns></returns>
 8 public static T CallSql<T>(string statement, object inParam)
 9 {
10     T outParam = default(T);
11 
12     try {
13         outParam = iSqlMapper.QueryForObject<T>(statement, inParam);
14     }
15     catch(Exception ex) {
16         Logger.Error("Sql: " + ex.Message + ex.StackTrace);
17         throw (new Exception(ex.Message));
18     }
19 
20     Logger.Info("exec Sql " + statement + " success");
21     return outParam;
22 }
23 
24 /// <summary>
25 /// 调用存储过程
26 /// </summary>
27 /// <typeparam name="T"></typeparam>
28 /// <param name="statement"></param>
29 /// <param name="inParam"></param>
30 /// <returns></returns>
31 public static T CallProc<T>(string statement, object inParam)
32 {
33     T outParam = default(T);
34 
35     try
36     {
37         outParam = iSqlMapper.QueryForObject<T>(statement, inParam);
38     }
39     catch (Exception ex)
40     {
41         Logger.Error("Proc: " + ex.Message + ex.StackTrace);
42         throw (new Exception(ex.Message));
43     }
44 
45     Logger.Info("exec Proc " + statement + " success");
46     return outParam;
47 }

行SQL或存储过程

实则,两者没有太要命区别,只是为着分开而分开。

瞩目,上述只是调用 QueryForObject 获取一个目标,如果是取列表,需要调用
QueryForList。

style=”font-size: 15px; font-family: comic sans ms,sans-serif;”>存储过程

倘若是运用 iBatis 调用存储过程,需要加上如下标签

[1]. parameterMaps +
parameterMap

储存过程参数配置,标签地位等与 resultMaps + resultMap 标签。

<!-- 存储过程输入参数配置 -->
<parameterMaps>
    <parameterMap id="parameterMapID" class="参数类型(Hashtable or map)">
        <parameter property="Param1" column="数据库列1" direction="Input" />
        <parameter property="Param2" column="数据库列2" type="string" dbType="binary" direction="Input" />
        <parameter ... ... />
        <parameter property="Param_x" column="数据库列x" direction="Output" />
        <parameter property="Param_y" column="数据库列y" direction="Output" />
    </parameterMap>
</parameterMaps>

[2]. procedure

仓储过程设置,在 <statements> 
标签中布局。

<statements>
  <procedure id="procedureID" parameterMap="parameterMapID" resultMap="resultMapID" remapResults="true">
    <![CDATA[
       DatabaseName.ProcedureName (eg: RVC.Pr_QueryUserInfo)
    ]]>
  </procedure>
</statements>

小心,如果是回到特定返回值类型,应该采取:resultClass=”特定返回值类型” 

[3].
remapResults

于行使 iBatis 中,务必设置该属性为
true,用于重置查询结果,否则,由于 iBatis
缓存机制的原因,会得重新的询问结果。

除去,注意存储过程的 return 只能回去
int 类型,若一旦回到外品类,请动 output

OGNL 表达式

iBatis 提供有力的 OGNL 表达式来解其他因素。

  • if
    语句:<if>,最普遍的气象是以动态SQL中来规则地连where子句的相同片
  • choose, when, otherwise 语句:类似switch语句
  • where 语句子:<where>,避免出现 SELECT * FROM TabName WHERE
    的情况
  • foreach 语句:<foreach>,允许指定使用集合

providers.config

提供常用数据库驱动程序支持信息清单,DataMapper
在该文件被搜索选定数据库的 provider 的概念。

// provider.config 配置文件结构
<?xml version="1.0" encoding="utf-8"?>

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

  <clear/>

  <provider
    name="DBName"
    description="The description of the DB"
    enabled="true or false"
    default="true or false" 
    parameterPrefix="@"
    ... ... 
  />
  <provider
  />

  ... ...

</providers>

在意其中的几只参数,如果多独数据库让
enabled=”true”,可以装中一个的 default=”true”
默认启动,parameterPrefix 代表参数化SQL语句被参数的前缀。

下分别给出一个 SQLServer 和 DB2 的以身作则

MyBatis 5MyBatis 6

 1 <provider
 2     name="sqlServer2.0"
 3     enabled="true"
 4     description="Microsoft SQL Server, provider V2.0.0.0 in framework .NET V2.0" 
 5     assemblyName="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
 6     connectionClass="System.Data.SqlClient.SqlConnection" 
 7     commandClass="System.Data.SqlClient.SqlCommand"
 8     parameterClass="System.Data.SqlClient.SqlParameter"
 9     parameterDbTypeClass="System.Data.SqlDbType"
10     parameterDbTypeProperty="SqlDbType"
11     dataAdapterClass="System.Data.SqlClient.SqlDataAdapter"
12     commandBuilderClass=" System.Data.SqlClient.SqlCommandBuilder"
13     usePositionalParameters = "false"
14     useParameterPrefixInSql = "true"
15     useParameterPrefixInParameter = "true" 
16     parameterPrefix="@"
17     allowMARS="false"
18     allowMultiQueries="true"
19 />

SQLServer

MyBatis 7MyBatis 8

 1 <provider
 2     name="iDb2.9"
 3     description="IBM DB2 Provider, V 10.0"
 4     enabled="true"
 5     default="true"
 6     assemblyName="IBM.Data.DB2, Culture=neutral, PublicKeyToken=7c307b91aa13d208, Custom=null"
 7     connectionClass="IBM.Data.DB2.DB2Connection"
 8     commandClass="IBM.Data.DB2.DB2Command"
 9     parameterClass="IBM.Data.DB2.DB2Parameter"
10     parameterDbTypeClass="IBM.Data.DB2.DB2Type"
11     parameterDbTypeProperty="DB2Type"
12     dataAdapterClass="IBM.Data.DB2.DB2DataAdapter"
13     commandBuilderClass="IBM.Data.DB2.DB2CommandBuilder"
14     usePositionalParameters="true"
15     useParameterPrefixInSql="false"
16     useParameterPrefixInParameter="false"
17     parameterPrefix=""
18     allowMARS="false"
19 />

DB2

主导用

iBatis 最根本之老三单公文

style=”font-size: 15px;”>SqlMapXxxx.config、MyXxxx.xml、providersXxxx.config

专注,SqlMapXxxx.config、providersXxxx.config
文件应在 DataMapper 运作时方可找到的地方。

率先,要生载 iBatis .Net 使用的 .dll 文件,可自行百度 iBatis.Net 哈

  • IBatis.DataMapper.1.6.2.bin.zip
  • IBatis.DataAccess.1.9.2.bin.zip

涉嫌的第一 .dll 文件如下

IBatisNet.Common.dll: 由DataAccess和DataMapper组成的共享程序集
IBatisNet.DataMapper.dll: DataMapper框架
IBatisNet.DataAccess.dll: DataAccess框架
IBatisNet.Common.Logging.Log4Net.dll: Log4Net集成记录器, 和Log4Net.dll配合使用

此外,下载的 ibatis.net 在解压目录下发出几乎单 .xsd 文件,该公文是 .xml
文件的证实文件

SqlMapConfig.xsd, SqlMap.xsd, provider.xsd, DaoConfig.xsd

以那个拷贝到 VS 安装目录,用于在 VS 中支持 XML 自动唤醒

%VsInstallDir%\xml\Schemas

以解压目录下还发几只 .xml 文件

IBatisNet.Common.xml、IBatisNet.DataMapper.xml、IBatisNet.DataAccess.xml、IBatisNet.Common.Logging.Log4Net.xml、log4net.xml

将该拷贝到 VS .NET Framework 的设置目录,用于编写代码时收获程序的API说明

C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/zh-CN

[1].
ISqlMapper

拖欠 API 提供数据访问层涉及到的章程

// 查询方法
[1]. QueryForObject()
[2]. QueryForList()
[3]. QueryForMap()
[4]. QueryForDictionary()

// 增、删、更新方法
object Insert(string statementName, object parameterObject);
int Update(string statementName, object parameterObject);
int Delete(string statementName, object parameterObject);

只顾,”Map” 这个称谓是 Java 里的,按 .NET
的动感应该是 Dictionary,所以 iBatis.NET同时提供了 “Dictionary”
对应之不二法门。

[2].
自动结果映射

欠特性可经过三种艺术使用

  • 单列查询
  • 固定类列表查询
  • 动态列表查询

照耀参数用于定义参数的有序列表,与查询语句的占位符相匹配。

[3].
iBatis初始化

private static ISqlMapper iSqlMapper = null;

/// filePath: 配置文件 SqlMapXxxx.config (相对)路径
public static void StartIBatisMapXxxx(string filePath)
{
    DomSqlMapBuilder builder = new DomSqlMapBuilder();
    iSqlMapper = builder.Configure(filePath);

    // 非Web请求线程需要加上该行
    iSqlMapper.SessionStore = new IBatisNet.DataMapper.SessionStore.HybridWebThreadSessionStore(iSqlMapper.Id);

    Logger = LogManager.GetLogger("iBatis");
}

每当 iBatis 中,SqlMapper 对象默认是单例模式实现。除上述办法外,也得透过
Mapper 类的静态 Instance() 属性实例化。

Demo
测试

下被闹一个应用 iBatis 的简短 Demo,注意一点,新建项目时要确认 .Net
框架的版本

默认是 .NET Framework 4 Client Profile,替换为 .NET Framework 4

第一为闹布局文件(包含日志记录配置信息),在 app.config或web.config
中安排

1)直接当控制台显示

MyBatis 9MyBatis 10

 1 <configuration>
 2   <configSections>
 3     <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
 4     <sectionGroup name="iBATIS">
 5       <section name="logging" type="IBatisNet.Common.Logging.ConfigurationSectionHandler, IBatisNet.Common" />
 6     </sectionGroup>
 7   </configSections>
 8   
 9   <iBATIS>
10     <logging>
11       <logFactoryAdapter type="IBatisNet.Common.Logging.Impl.ConsoleOutLoggerFA, IBatisNet.Common">
12         <arg key="showLogName" value="true" />
13         <arg key="showDataTime" value="true" />
14         <arg key="level" value="ALL" />
15         <arg key="dateTimeFormat" value="[MM-dd HH:mm:ss]" />
16       </logFactoryAdapter>
17     </logging>
18   </iBATIS>
19 </configuration>

iBATIS info in Console

要注意,标签 <iBATIS>
万万不能写成 <iBatis>,否则无法输出

MyBatis 11

这时,配置文件被并未采取 log4net 配置,要惦记在程序中施行 Logger.Info/Warn
记录日志,必须初始化

IBatisNet.Common.Logging.ILog Logger = 
    IBatisNet.Common.Logging.LogManager.GetLogger("iBatis");

下  IBatisNet.Common.Logging
组件初始化 Logger。

2)日志输出到文件

MyBatis 12MyBatis 13

 1 <configuration>
 2   <configSections>
 3     <sectionGroup name="iBATIS">
 4       <section name="logging" type="IBatisNet.Common.Logging.ConfigurationSectionHandler, IBatisNet.Common"/>
 5     </sectionGroup>
 6     <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
 7   </configSections>
 8 
 9   <!-- (2). 利用log4net输出日志到文件 -->
10   <iBATIS>
11     <logging>
12       <logFactoryAdapter type="IBatisNet.Common.Logging.Impl.Log4NetLoggerFA, IBatisNet.Common.Logging.Log4Net">
13         <arg key="configType" value="inline"/>
14       </logFactoryAdapter>
15     </logging>
16   </iBATIS>
17 
18   <log4net>
19     <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
20       <file value="Log\" />
21       <appendToFile value= "true" />
22       <datePattern value= "yyyyMMdd&quot;.log&quot;" />
23       <rollingStyle value= "Date" />
24       <staticLogFileName value="false" />
25       <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
26       <layout type="log4net.Layout.PatternLayout, log4net">
27         <param name="ConversionPattern" value="[%d{HH:mm:ss,fff}] [%t] %-5p %c-(%line)  %m%n" />
28       </layout>
29     </appender>
30     
31     <appender name="RollingConsoleAppender" type="log4net.Appender.ConsoleAppender">
32       <layout type="log4net.Layout.PatternLayout">
33         <param name="ConversionPattern" value="[%d{HH:mm:ss,fff}] [%t] %-5p %c-(%line)  %m%n"/>
34       </layout>
35     </appender>
36 
37     <root name="iBatis">
38       <level value="ALL"/>
39       <appender-ref ref="RollingLogFileAppender"/>
40       <appender-ref ref="RollingConsoleAppender"/>
41     </root>
42 
43     <!-- 打印错误信息的级别 
44     <logger name="IBatisNet.DataMapper.Configuration.Cache.CacheModel">
45       <level value="DEBUG"/>
46     </logger>
47     <logger name="IBatisNet.DataMapper.Configuration.Statements.PreparedStatementFactory">
48       <level value="DEBUG"/>
49     </logger>
50     <logger name="IBatisNet.DataMapper.LazyLoadList">
51       <level value="DEBUG"/>
52     </logger>
53     <logger name="IBatisNet.DataAccess.DaoSession">
54       <level value="DEBUG"/>
55     </logger>
56     <logger name="IBatisNet.DataMapper.SqlMapSession">
57       <level value="DEBUG"/>
58     </logger>
59     <logger name="IBatisNet.Common.Transaction.TransactionScope">
60       <level value="DEBUG"/>
61     </logger>
62     <logger name="IBatisNet.DataAccess.Configuration.DaoProxy">
63       <level value="DEBUG"/>
64     </logger>
65     -->
66   </log4net>
67   
68   <startup>
69     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
70   </startup>
71 </configuration>

iBatis log into file by
log4net

里头,<iBATIS> 标签的 configType 属性可设置也
inline、external、file、file-watch,推荐 inline:可以一直在 App.config 或
Web.Config 中安排 log4net 节点。

总得注意,log4net 的版,应该使用下充斥包吃之 1.2.10.0
版本,不要为此时髦的 2.0.8.0 版本。

下被闹当主函数着之初始化方法

string configFilePath = "app.config";
FileInfo fileinfo = new FileInfo(configFilePath);
log4net.Config.XmlConfigurator.ConfigureAndWatch(fileinfo);
ILog Logger = LogManager.GetLogger("iBatis");

以此采用 log4net 记录日志,可以直接以 log4net 组件初始化 Logger。

3)iBatis 调用存储过程

用 iBatis 调用SQL语句,在头里的 动态SQL
部分学习过,此处不再另行,下面要学习下调用存储过程。

系消息方可瞻仰:iBatis
调用存储过程

首先定义一个带来输出参数的存储过程,根据 ID 查询姓名

MyBatis 14MyBatis 15

 1 USE [Stu_sqh]
 2 GO
 3 
 4 SET ANSI_NULLS ON
 5 GO
 6 SET QUOTED_IDENTIFIER ON
 7 GO
 8 
 9 IF exists(select 1 from sysobjects where id=object_id('PR_QueryNameByID') and xtype='P')
10     DROP PROC PR_QueryNameByID 
11 GO
12 
13 CREATE PROC PR_QueryNameByID(
14     @ID        INT,
15     @O_RTCD    INT OUT,
16     @O_NAME    VARCHAR(20) OUT
17 )
18 as 
19 
20 SET @O_RTCD = 0;
21 SET @O_Name = '';
22 
23 BEGIN
24     select @O_Name = NAME
25     FROM [Stu_sqh].[dbo].[StudentInfo]
26     WHERE ID = @ID; 
27 END;
28 
29 RETURN 0;

PR_QueryNameByID

然后,在 MyXxxx.xml 中配置

<parameterMaps>
    <parameterMap id="QueryNameByIDParamMap" class="Hashtable">
      <parameter property="ID" column="ID" direction="Input" />
      <parameter property="O_RTCD" column="O_RTCD" direction="Output" />
      <parameter property="O_NAME" column="O_NAME" direction="Output" />
    </parameterMap>
</parameterMaps>

<procedure id="QueryNameByID" parameterMap="QueryNameByIDParamMap" resultClass="string" remapResults="true">
    <![CDATA[ PR_QueryNameByID ]]>
</procedure>

末段,调用该存储过程

Hashtable ht = new Hashtable();
ht.Add("ID", 101);
ht.Add("O_RTCD", 0);
ht.Add("O_NAME", "");
strig statement = "MyXxxx.QueryNameByID";
DataOperationHelper.CallProc<string>(statement, ht);
string stuName = (string)ht["O_NAME"];

扩大使用

(1)关于数据库查询性能提升方法

[a].
分页查询

极致实在有效。

[b].
延迟加载

Lazy Loading,需要常再次加载。在 SqlMapXxxx.config 文件中上加如下配置

// 延迟加载机制
<setting lazyLoadingEnabled="true"/>
// 字节码强制机制
<setting enhancementEnabled = "true" />

内部,字节码强制机制好 Lazy Loading 性能改善。

[c].
Cache机制

运用 Cache
查询,对于创新次数比较少的多寡较可行,但是得审慎使用Cache机制,避免出现第三正在对数据的翻新导致污染数据。

在 SqlMapXxxx.config 文件被补充加如下配置

// Cache机制
<setting cacheModelsEnabled="true"/>

结缘 CacheModel,在部署文件被,主要是 type、readOnly、serialize
三单特性

<cacheModel id="product-cache" type ="LRU" readOnly="true" serialize="false" />

其间,readOnly
代表缓存数据只念,读性能好,但数据更新会降低效率;serialize = true
表示全局数据缓存,反的表示有缓存、仅针对当下 Session 有效。

对 type,表示缓存实现机制,有 3 种档次

  • FIFO:先进先出型缓存,最先放入 Cache 中的多寡以为冠破
  • LRU:最近最少使用型缓存,当 Cache 达到预先设定的无比特别容量时,iBatis
    会按照 “最少使用” 原则用动用效率最少的对象由缓冲中排除
  • Memory:通常采取 WEAK 的 MEMORY 型 Cache 配置

此处被闹一个 CacheModel 的布局结点示例

<cacheModels>
  <cacheModel id = "person-cache" implementation = "MEMORY" >
     <flushInterval  hours = "24"/>  
     <flushOnExecute statement = "UpdateAccountViaInlineParameters"/>
     <flushOnExecute  statement = "UpdateAccountViaParameterMap"/>
     <property name = "Type" value = "Weak"/>
  </cacheModel>
</cacheModels>

针对 CacheModel 的几乎只基本点元素说明如下

flushInterval:设定缓存有效期
CacheSize:当前Cachemodel中最大的数据对象数量 
flushOnExecute:指定执行特定的Statement时,将缓存清空

特别注意 flushOnExecute,如 Update
操作将履新数据库信息,会造成缓存中之数码信息以及数据库被的实际数据信息有偏向,因此须用缓存清空避免脏数据出现。

下一场,在 <select> 标签中,对查询到的数码以 cache 机制

<statements>
    <select id="SelectAllPerson" resultMap="PersonInfoResult" cacheModel="person-cache">
      select ID, NAME, BIRTH_DATE, WEIGHT_KG, HEIGHT_M from PERSON     
    </select>
</statements>

通过该 id 获取到数码后,使用 CacheModel 的 “person-cache”
进行缓存,当又调整用该 id
数据查询时,直接由缓存中取数据,不用再行去查询数据库。

(2)关于避免 N+1查询 问题

率先了解什么是 N+1 查询问题,主要考虑以特别数据集的情事,特别是对主从表(父子表)的询问,容易生出N+1查询问题,由于准备加载父记录的多个子记录引起的。在询问父记录时,只需要1长达语句,若返回N条记录,那么尽管得重履行N条语句子来查询子记录,引发”N+1″问题。

哪避免,提供 2 种方式:

  • 缓加载:配置属性 lazyLoad=”true”,并没有完全解决数据库I/O问题,最要命情况下,对数据库的看次数和非延迟加载是千篇一律的。
  • 老是语句(join)方式来完全避免N+1查询问题:在
    iBatis 中运用 groupBy 特性:方法抢,但是内存占用大
  • 自打定义组件 RowHandler

连带信息参见:iBatis系列-数据库查询;

(3)获取特定项目的数据

[a].
获取 SQL 语句

在好几场景下,需要取得执行的动态SQL语句,如,SQL语句执行破产、将该语句打印及日志

public static string GetRuntimeSQL(ISqlMapper iSqlMapper, string selectFun, object inParam)
{
    string sql = string.Empty;
    try
    { 
        IMappedStatement iMappedStatement = iSqlMapper.GetMappedStatement(selectFun);
        ISqlMapSession iSession = iSqlMapper.CreateSqlMapSession();
        RequestScope requestScope = iMappedStatement.Statement.Sql.GetRequestScope(iMappedStatement, inParam, iSession);
        iMappedStatement.PreparedCommand.Create(requestScope, iSession, iMappedStatement.Statement, inParam);

        sql = requestScope.PreparedStatement.PreparedSql;
        IDbCommand cmd = requestScope.IDbCommand;
        foreach (IDbDataParameter it in cmd.Parameters) {
            sql += "; [" + it.ParameterName + " = " + it.Value + "] ";
        }
        iSession.CloseConnection();
    }
    catch(Exception ex)
    {
        Logger.Info("GetRuntimeSQL exec failed: " + ex.Message + ex.StackTrace);
        return null;
    }
    return sql;
}

[b].
获取存储过程

抱方式类似获取 SQL
语句,额外维护一个参数方向的字典集,输出信息会越加明白

proc = requestScope.PreparedStatement.PreparedSql; // 存储过程名字
IDbCommand cmd = requestScope.IDbCommand;
foreach (IDbDataParameter it in cmd.Parameters) {
    proc += "; [" + it.ParameterName + " = " + it.Value + "] ";
}
iSession.CloseConnection();

具体方法可参见:iBatis.Net实现返回DataTable和DataSet对象

[c].
返回 DataSet 类型数据

于好几情况下,需要回到 DataSet 格式的数额,如果回去 DataTable,则 dataSet.Table[0]; 

public static DataSet QueryForDataSet(ISqlMapper iSqlMapper, string selectFun, object inParam)
{
    DataSet dataSet = new DataSet();
    try
    {               
        IMappedStatement iMappedStatement = iSqlMapper.GetMappedStatement(selectFun);
        ISqlMapSession iSession = iSqlMapper.CreateSqlMapSession();
        RequestScope requestScope = iMappedStatement.Statement.Sql.GetRequestScope(iMappedStatement, inParam, iSession);
        iMappedStatement.PreparedCommand.Create(requestScope, iSession, iMappedStatement.Statement, inParam);

        FieldInfo info = requestScope.IDbCommand.GetType().GetField("_innerDbCommand", BindingFlags.NonPublic | BindingFlags.Instance);
        IDbCommand cmd = (IDbCommand)info.GetValue(requestScope.IDbCommand);
        IDbDataAdapter adapter = iSession.CreateDataAdapter(cmd);
        adapter.Fill(dataSet);
    }
    catch (Exception ex)
    {
        Logger.Info("QueryForDataSet exec failed: " + ex.Message + ex.StackTrace);
        return null; 
    }          
    return dataSet;
}

留神,在 iBatis 1.6 版本后,用 DbCommandDecorator 包装了 DbCommand,直接

iSession.CreateDataAdapter(requestScope.IDbCommand).Fill(ds)

会提示

无法将类型为“IBatisNet.DataMapper.Commands.DbCommandDecorator”的对象强制转换为类型“System.Data.SqlClient.SqlCommand”

可应用反射的方式,从 DbCommandDecorator 中取出 innerDbCommand
字段即可。

下面被闹调用方式以及对应的部署

<select id="selectInfoByID" parameterClass="int" resultClass="System.Data.DataSet">
  select * from dbo.StudentInfo where id=#id#
</select>

int id = 101;
string statement = "MyXxxx.selectInfoByID";
ISqlMapper iSqlMapper = DataOperationHelper.iSqlMapper;
DataSet ds = DataOperationHelper.QueryForDataSet(iSqlMapper, statement, id);
Console.WriteLine(ds.GetXml());

小心,务必写成 System.Data.DataSet,不可知简写。

此间,返回 DataSet/DataTable,并不曾采用 iBatis 的中查询办法,区别与
CallSql 和 CallProc。

调用存储过程返回 DataSet/DataTable
可能会见遇上的题目,参见:http://blog.csdn.net/netjxz/article/details/1675430

行使
iBatis 应注意的题材

[1].
#
与 $

  • # 是内联参数,可以开展编译、类型匹配,安全性能好,$
    是文本替换,不支持数据类型匹配;
  • # 可用于变量替换,$ 仅仅是字符串拼接、存在 SQL 注入风险;
  • 对于可能吧整型变量可能啊字符串变量的地方,务必以
    #,对于自然是整型变量的地方,可以下 $;

对此变量,推荐用 #,可以使得防 SQL 注入。

update #tableName# set STATUS = #status# where ID = #id#

只顾留心又留意,重要之工作说3整,谨慎采用替换($)语法。

[2].
iBatis
的 .dll 文件以及 VS .NET FrameWork 4.0 版本不般配的题材

题目:项目遭到援了 .dll
文件,但是编译运行报错:不在相关的 .dll 文件

化解措施:将 VS 的.NET FrameWork 4.0
框架改吗 .NET FrameWork 3.5

[3].
提示数据库驱动程序不针对

题目:引用的 System.Data.SqlClient.dll 版本及 providers.config
中著录之本子不一样

缓解办法:通过 Assembly 读取
System.Data.SqlClient.dll 文件的 FullName,填入providers.config
文件相应使的 assemblyName 参数

System.Reflection.Assembly.LoadFile(@"...\System.Data.OracleClient.dll").FullName

关于在 Java 中动用 iBatis 可参见上述在 .Net 中的用法,有待于更为读书。

参考

iBatis .Net –
博客园;框架:Ibatis.Net学习;

至于IBatis.Net的习记录 –
几只问题;

iBATIS.NET – DataMapper Application Framework – DataMapper Developer
Guide;

深切剖析 iBATIS Java
框架的网架构和照原理;

网站地图xml地图