iBaits学习2

一,        iBatis 简介

 

iBatis 是一种数据库持续层的 ORM 框架。使用简单的 XML 配置文件将 Java   Bean 映射成 PreparedStatement 的输入参数和 ResultSet 结果集。

 

在不是很复杂的情况下,我们甚至可以使用 HashMap 而不是 Java Bean 来映射 PreparedStatement 的输入参数和 ResultSet 结果集,从而节省开发时间与成本。或者,我们可以使用一些辅助工具来帮助我们通过 XML 配置生成对应的 Java Bean.

 

二,        iBatis 工作原理 , 流程

 

iBatis 使用简单的 XML 描述文件将 Java Bean Map 实现和基本数据类型的包装类( String Integer 等)映射成 JDBC PreparedStatement 的输入参数和 ResultSet 结果集。具体工作流程如下:

 

1 .在 sqlMapConfig XML 配置文件中进行数据库连接的配置, XML 配置文件名称任意,比如 sql-map-config.xml

 

2 .在 sqlMapConfig XML 配置文件中引用 sqlMap XML 配置文件

 

<sqlMap resource="examples/sqlmap/maps/Person1.xml" />

 

<sqlMap url="file:///c:/config/Customer.xml " />

 

 

3 .在 sqlMap XML 配置文件中进行 SQL 文的配置,文件名称任意,比如 Person1.xml

 

4 .通过 SqlMapClientBuilder 生成具体的操作 sqlMap 配置文件中SQL文的IBATIS对象 SqlMapClient

 

String resource = "config/ibatis/sql-map-config.xml";                  

 

Reader reader = Resources.getResourceAsReader (resource);                      

 

SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

 

 

5 SqlMapClient 对象提供函数,函数的参数对应替换 sqlMap 配置文件中的 id,parameter 等等属性,完成SQL文的执行。具体参照 iBatis API

 

public List queryForList(String statementName, Object parameterObject,

 

int skipResults, int maxResults)

 

statement:sqlMap 配置中 id 属性, parameterObject:sqlMap 配置中 parameterXXX 属性

 

 

iBatis 的工作重点在于配置文件的做成上,尤其 sqlMap 配置文件的做成是我们需要重点学习的。

 

三,        SqlMapConfig.xml

 

配置例子如下,各个标签的说明参考官方文档。比较容易理解,这里不做整理

 

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

 

<!DOCTYPE sqlMapConfig

 

PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"

 

"http://www.ibatis.com/dtd/sql-map-config-2.dtd">

 

<sqlMapConfig>

 

<properties resource=" examples/sqlmap/maps/SqlMapConfigExample.properties " />

 

<settings

 

cacheModelsEnabled="true"

 

enhancementEnabled="true"

 

lazyLoadingEnabled="true"

 

maxRequests="32"

 

maxSessions="10"

 

maxTransactions="5"

 

useStatementNamespaces="false"

 

/>

 

<typeAlias alias="order" type="testdomain.Order"/>

 

<transactionManager type="JDBC" >

 

<dataSource type="SIMPLE">

 

<property name="JDBC.Driver" value="${driver}"/>

 

<property name="JDBC.ConnectionURL" value="${url}"/>

 

<property name="JDBC.Username" value="${username}"/>

 

<property name="JDBC.Password" value="${password}"/>

 

<property name="JDBC.DefaultAutoCommit" value="true" />

 

<property name="Pool.MaximumActiveConnections" value="10"/><property name="Pool.MaximumIdleConnections" value="5"/>

 

<property name="Pool.MaximumCheckoutTime" value="120000"/>

 

<property name="Pool.TimeToWait" value="500"/>

 

<property name="Pool.PingQuery" value="select 1 from ACCOUNT"/>

 

<property name="Pool.PingEnabled" value="false"/>

 

<property name="Pool.PingConnectionsOlderThan" value="1"/>

 

<property name="Pool.PingConnectionsNotUsedFor" value="1"/>

 

</dataSource>

 

</transactionManager>

 

<sqlMap resource="examples/sqlmap/maps/Person.xml" />

 

<sqlMap url="file:///c:/config/Customer.xml " />

 

</sqlMapConfig>

 

 

以上,主要注意 DB 连接情报的配置方法,采用了 Java 的标准 Properties 文件。

 

<properties resource=" examples/sqlmap/maps/SqlMapConfigExample.properties " />

 

       然后在 XML 中引用 properties 文件中的定义。

 

           <property name="JDBC.Driver" value="${driver}"/>

 

四,        SqlMap.xml 总体印象

 

较复杂的例子:

 

<sqlMap id=”Product”>

 

<cacheModel id=”productCache” type=”LRU”>

 

<flushInterval hours=”24”/>

 

<property name=”size” value=”1000” />

 

</cacheModel>

 

<typeAlias alias=”product” type=”com.ibatis.example.Product” />

 

<parameterMap id=”productParam” class=”product”>

 

<parameter property=”id”/>

 

</parameterMap>

 

<resultMap id=”productResult” class=”product”>

 

<result property=”id” column=”PRD_ID”/>

 

<result property=”description” column=”PRD_DESCRIPTION”/>

 

</resultMap>

 

<select id=”getProduct” parameterMap=”productParam”

 

resultMap=”productResult” cacheModel=”product-cache”>

 

select * from PRODUCT where PRD_ID = ?

 

</select>

 

</sqlMap>

 

 

      以上例子简化版:

 

<sqlMap id=”Product”>

 

<select id=”getProduct” parameterClass=” com.ibatis.example.Product”

 

resultClass=”com.ibatis.example.Product”>

 

Select

 

PRD_ID as id,

 

PRD_DESCRIPTION as description

 

From PRODUCT

 

Where PRD_ID = #id#

 

</select>

 

</sqlMap>

 

 

五,        Statement 语法,类型,及其属性和特点

 

1. 语法

 

<statement

 

  id=”statementName”

 

[parameterClass=”some.class.Name”]

 

[resultClass=”some.class.Name”]

 

[parameterMap=”nameOfParameterMap”]

 

[resultMap=”nameOfResultMap”]

 

[cacheModel=”nameOfCache”]

 

>

 

select * from PRODUCT where PRD_ID = [?|#propertyName#] order by [$simpleDynamic$]

 

</statement>

 

[] 内为可选项,不是必须存在的。

 

 

2.Statement 类型,属性,特点

 

 

六,        关于映射时输入值的匹配问题

 

1.     SqlMapClient 如何从 SqlMap 的配置文件中找到对应的 SQL

 

通过类函数的参数 statementName 与配置文件中 statement 配置的 id 相匹配

 

2.     bean 中的数据如何映射给 SQL 文中对应的输入参数

 

a.     通过参数变量名称与 bean 中对应属性名称相匹配

 

<statement id=”statementName” parameterClass=” examples.domain.Product”>

 

insert into PRODUCT values (#id#, #description#, #price#)

 

</statement>

 

 

b.     通过参数变量的出现顺序相匹配

 

<parameterMap id=”insert-product-param” class=”com.domain.Product”>

 

<parameter property=”id”/>

 

<parameter property=”description”/>

 

</parameterMap>

 

<statement id=”insertProduct” parameterMap=”insert-product-param”>

 

insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (?,?);

 

</statement>

 

 

3.     map 中的数据如何映射给 SQL 文中对应的输入参数

 

a.     通过参数变量名称与 map 中对应 key 相匹配

 

<statement id=”statementName” parameterClass=” java.util.Map”>

 

insert into PRODUCT values (#id#, #description#, #price#)

 

</statement>

 

HashMap hm = new HashMap();

 

hm.put(“id”,”value”);

 

hm.put(“description”,”value”);

 

hm.put(“price”,”value”);

 

sqlMapClient.queryForList(“statementName”, hm,…………);

 

 

4.     基本数据类型的数据如何映射给 SQL 文中对应的输入参数

 

基本数据类型与参数 1 1 ,没啥匹配的问题。不过官方的开发指南中强调参数要写成 #value# 这种写法,原因不明。

 

<statement id=”insertProduct” parameter=”java.lang.Integer”>

 

select * from PRODUCT where PRD_ID = #value#

 

</statement>

 

 

七,        关于映射时返回值的匹配问题

 

1.     查询结果如何映射给 bean 中的对应属性

 

a.     通过查询结果的字段名称与 bean 中对应属性名称相匹配

 

<statement id=”getProduct” resultClass=”com.ibatis.example.Product”>

 

select

 

PRD_ID as id,

 

PRD_DESCRIPTION as description

 

from PRODUCT

 

where PRD_ID = #value#

 

</statement>

 

官方的开发指南中说这种写法叫做隐式 ResultMap

 

 

b.     指定查询结果的字段名称与 bean 中对应属性名称的映射关系

 

<resultMap id=”get-product-result” class=”com.ibatis.example.Product”>

 

<result property=”id” column=”PRD_ID”/>

 

<result property=”description” column=”PRD_DESCRIPTION”/>

 

<result property=”subCode” column=”PRD_SUB_CODE” nullValue=”-999”/>

 

</resultMap>

 

 

以上,数据类型通过反射与对应的属性类型自动匹配,极少数时候可能需要通过 resultMap javaType 属性进行设定,参考后面关于 Result Map 外部形式中各个参数的说明

 

2.     查询结果如何设定给 Map

 

a.     通过查询结果的字段名称与 map 中对应 key 相匹配

 

<resultMap id=”get-product-result” class=”java.util.HashMap”>

 

<result property=”id” column=”PRD_ID”/>

 

<result property=”code” column=”PRD_CODE”/>

 

<result property=”description” column=”PRD_DESCRIPTION”/>

 

<result property=”suggestedPrice” column=”PRD_SUGGESTED_PRICE”/>

 

</resultMap>

 

<statement id=”getProductCount” resultClass=”java.util.HashMap”>

 

select * from PRODUCT

 

</statement>

 

 

b.     指定查询结果的字段名称与 bean 中对应属性名称的映射关系

 

bean 基本相同,参考使用 bean 作为返回结果的写法

 

3.     查询结果如何映射给基本数据类型

 

只能指定一个返回值,名字可以随便,一般采用 value,val

 

<resultMap id=”get-product-result” class=”java.lang.String”>

 

<result property=”value” column=”PRD_DESCRIPTION”/>

 

</resultMap>

 

或者

 

<statement id=”getProductCount” resultClass=”java.lang.Integer”>

 

select count(1) as value

 

from PRODUCT

 

</statement>

 

 

八,        关于 Parameter Map 外部形式中各个参数的说明

 

<parameterMap id=”parameterMapName” [class=”com.domain.Product”]>

 

<parameter

 

property =”propertyName”

 

[jdbcType=”VARCHAR”]

 

[javaType=”string”]

 

[nullValue=”NUMERIC”]

 

[null=”-9999999”]/>

 

<parameter …… />

 

<parameter …… />

 

</parameterMap>

 

1.JdbcType

 

属性 jdbcType 用于显式地指定给本属性( property )赋值的数据库字段的数据类型。对于某些特定的操作,如果不指定字段的数据类型,某些 JDBC Driver 无法识别字段的数据类型。

 

正常情况下,只有当字段可以为 NULL 时才需要 jdbcType 属性。另一需要指定 jdbcType 属性的情况是字段类型为日期时间类型的情况。因为 Java 只有一个 Date 类型( java.util.Date ),而大多数 SQL 数据库有多个-通常至少有 3 种。因此,需要指定字段类型是 DATE 还是 DATETIME

 

注意!当使用 Oracle Driver 时,如果没有给可以为 NULL 的字段指定 jdbcType 属性,当试图给这些字段赋值 NULL 时,会出现“ Invalid column type ”错误。

 

2.javaType

 

属性 javaType 用于显式地指定被赋值参数 Java 属性的类名。正常情况下,这可以通过反射从 Java Bean 的属性获得

 

3.nullValue, null

 

   用于指定 NULL 的替换值。就是说,当 Java Bean 的属性值等于指定值时,相应的字段将赋值 NULL 。这个特性允许在应用中给不支持 null 的数据类型(即 int double float 等)赋值 null 。当这些数据类型的属性值匹配 null 值(即匹配 -9999 )时, NULL 将代替 null 值写入数据库。

 

 

      一个完整的例子

 

<parameterMap id=”insert-product-param” class=”com.domain.Product”>

 

<parameter

 

property=”id”

 

jdbcType=”NUMERIC”

 

javaType=”int”

 

nullValue=”-9999999”/>

 

<parameter

 

property=”description”

 

jdbcType=”VARCHAR”

 

nullValue=”NO_ENTRY”/>

 

</parameterMap>

 

<statement id=”insertProduct” parameterMap=”insert-product-param”>

 

insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (?,?);

 

</statement>

 

 

      简化写法

 

<statement id=”insertProduct” parameterClass=”com.domain.Product”>

 

insert into PRODUCT (PRD_ID, PRD_DESCRIPTION)

 

values (#id:NUMERIC#, #description:VARCHAR#);

 

</statement>

 

或者:

 

<statement id=”insertProduct” parameterClass=”com.domain.Product”>

 

insert into PRODUCT (PRD_ID, PRD_DESCRIPTION)

 

values (#id:NUMERIC:-999999#, #description:VARCHAR:NO_ENTRY#);

 

</statement>

 

 

九,        Result Map 外部形式中各个参数的说明

 

<resultMap id=”resultMapName” class=”some.domain.Class” [extends=”parent-resultMap”]>

 

<result property=”propertyName” column=”COLUMN_NAME”

 

[columnIndex=”1”]

 

[javaType=”int”]

 

[jdbcType=”NUMERIC”]

 

[nullValue=”-999999”]

 

[select=”someOtherStatement”]

 

/>

 

<result ……/>

 

<result ……/>

 

<result ……/>

 

</resultMap>

 

1. columnIndex

 

属性 columnIndex 是可选的,用于改善性能。属性 columnIndex 的值是 ResultSet 中用于赋值 Java Bean 属性的字段次序号。在 99 %的应用中,不太可能需要牺牲可读性来换取性能。使用 columnIndex ,某些 JDBC Driver 可以大幅提高性能,某些则没有任何效果。

 

2.javaType

 

属性 javaType 用于显式地指定被赋值的 Java Bean 属性的类型。正常情况下,这可以通过反射从 Java Bean 的属性获得,但对于某些映射(例如 Map XML document ),框架不能通过这种方法来获知。如果没有设置 javaType ,同时框架也不能获知类型信息,类型将被假定为 Object

 

3.jdbcType,nullValue, null

 

   Parameter Map

 

4.select

 

属性 select 用于描述对象之间的关系,并自动地装入复杂类型(即用户定义的类型)属性的数据。属性 select 的值必须是另外一个 mapped statement 元素的名称。在同一个 result 元素中定义的数据库字段( column 属性)以及 property 属性,将被传给相关的 mapped statement 作为参数。因此,字段的数据类型必须是 SQL Map 支持的简单数据类型。关于简单数据类型和复杂类型之间映射 / 关系的信息,参照后面章节更详细的讨论。

 

具体参考稍后关于复杂类型属性的例子

 

 

十,        复杂类型属性说明

 

1 .关于复杂类型属性的例子

 

<resultMap id=”get-product-result” class=”com.ibatis.example.Product”>

 

<result property=”id” column=”PRD_ID”/>

 

<result property=”description” column=”PRD_DESCRIPTION”/>

 

<result property=”category” column=”PRD_CAT_ID” select=”getCategory”/>

 

</resultMap>

 

<resultMap id=”get-category-result” class=”com.ibatis.example.Category”>

 

<result property=”id” column=”CAT_ID”/>

 

<result property=”description” column=”CAT_DESCRIPTION”/>

 

</resultMap>

 

<statement id=”getProduct” parameterClass=”int” resultMap=”get-product-result”>

 

select * from PRODUCT where PRD_ID = #value#

 

</statement>

 

<statement id=”getCategory” parameterClass=”int” resultMap=”get-category-result”>

 

select * from CATEGORY where CAT_ID = #value#

 

</statement>

 

 

         避免 N 1 Select 1:1  

 

<resultMap id=”get-product-result” class=”com.ibatis.example.Product”>

 

<result property=”id” column=”PRD_ID”/>

 

<result property=”description” column=”PRD_DESCRIPTION”/>

 

<result property=”category.id” column=”CAT_ID” />

 

<result property=”category.description” column=”CAT_DESCRIPTION” />

 

</resultMap>

 

<statement id=”getProduct” parameterClass=”int” resultMap=”get-product-result”>

 

select *

 

from PRODUCT, CATEGORY

 

where PRD_CAT_ID=CAT_ID

 

and PRD_ID = #value#

 

</statement>

 

 

2 .关于复杂类型级和属性的例子

 

<resultMap id=”get-category-result” class=”com.ibatis.example.Category”>

 

<result property=”id” column=”CAT_ID”/>

 

<result property=”description” column=”CAT_DESCRIPTION”/>

 

<result property=”productList” column=”CAT_ID” select=” getProductsByCatId”/>

 

</resultMap>

 

<resultMap id=”get-product-result” class=”com.ibatis.example.Product”>

 

<result property=”id” column=”PRD_ID”/>

 

<result property=”description” column=”PRD_DESCRIPTION”/>

 

</resultMap>

 

<statement id=”getCategory” parameterClass=”int” resultMap=”get-category-result”>

 

select * from CATEGORY where CAT_ID = #value#

 

</statement>

 

<statement id=”getProductsByCatId” parameterClass=”int” resultMap=”get-product-result”>

 

select * from PRODUCT where PRD_CAT_ID = #value#

 

</statement>

 

 

         避免 N 1 Select 1:1  

 

暂时无解,在新版本中可能会对应

 

 

3 .组合键值或多个复杂参数属性

 

<resultMap id=”get-order-result” class=”com.ibatis.example.Order”>

 

<result property=”id” column=”ORD_ID”/>

 

<result property=”customerId” column=”ORD_CST_ID”/>

 

<result property=”payments” column=”{itemId=ORD_ID, custId=ORD_CST_ID}”

 

select=” getOrderPayments”/>

 

</resultMap>

 

<statement id=”getOrderPayments” resultMap=”get-payment-result”>

 

select * from PAYMENT

 

where PAY_ORD_ID = #itemId#

 

and PAY_CST_ID = #custId#

 

</statement>

 

 

十一,    在查询 statement 中指定 cacheModel 属性

 

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

 

<flushInterval hours="24"/>

 

<flushOnExecute statement="insertProduct"/>

 

<flushOnExecute statement="updateProduct"/>

 

<flushOnExecute statement="deleteProduct"/>

 

<property name=”cache-size” value=”1000” />

 

</cacheModel>

 

<statement id=”getProductList” cacheModel=”product-cache”>

 

select * from PRODUCT where PRD_CAT_ID = #value#

 

</statement>

 

1 Serializable 可读写缓存

 

正如您所知道的,只对当前 Session 有效的缓存对整体应用性能的提高作用有限。 Serializable 可读写缓存可以提高整体应用(而不仅仅是每个 Session )的性能。这种缓存为每一个 Session 返回缓存对象不同的实例(复本)。因此每一个 Session 都可以安全修改返回的对象。不同之处在于,通常您希望从缓存中得到同一个对象,但这种情况下得到的是不同的对象。还有,每一个缓冲在 Serializable 缓存的对象都必须是 Serializable 的。这意味着不能同时使用 Serializable 缓存和延迟加载,因为延迟加载代理不是 Serializable 的。想知道如何把 Serializable 缓存,延迟加载和联合查询结合起来使用,最好的方法是尝试。要使用 Serializable 缓存,设置 readOnly= false ”和 serialize= true ”。缺省情况下,缓存是只读模式,不使用 Serializable 缓存。只读缓存不需要 Serializable

 

2 Type

 

    a.type=”MEMORY”

 

MEMORY cache 实现只认识一个 <property> 元素。这个名为“ reference-type ”属性的值必须是 STRONG SOFT WEAK 三者其一。这三个值分别对应于 JVM 不同的内存 reference 类型。

 

<property name=”reference-type” value=”WEAK” />

 

    b.type=”LRU”

 

LRU Cache 实现用“近期最少使用”原则来确定如何从 Cache 中清除对象。

 

       <property name=”cache-size” value=”1000” />

 

    c.type=”FIFO”

 

       FIFO Cache 实现用“先进先出”原则来确定如何从 Cache 中清除对象。

 

<property name=”size” value=”1000” />

 

d.type= OSCACHE   没用过,没研究过。这个不太懂,哈

 

OSCACHE Cache 实现是 OSCache2.0 缓存引擎的一个 Plugin 。它具有高度的可配置性,分布式,高度的灵活性。

 

OSCACHE 实现不使用 property 元素,而是在类路径的根路径中使用标准的 oscache.properties 文件进行配置。在 oscache.properties 文件中,您可以配置 Cache 的算法(和上面讨论的算法很类似), Cache 的大小,持久化方法(内存,文件等)和集群方法。

 

要获得更详细的信息,请参考 OSCache 文档。 OSCache 及其文档可以从 OpenSymphony 网站上获取:

 

http://www.opensymphony.com/oscache/

 

 

十二,    动态 Mapped Statement

 

<select id="dynamicGetAccountList"

 

cacheModel="account-cache"

 

resultMap="account-result"

 

>

 

select * from ACCOUNT

 

<isGreaterThan prepend="and" property="id" compareValue="0">

 

where ACC_ID = #id#

 

</isGreaterThan>

 

order by ACC_LAST_NAME

 

</select>

 

上面的例子中,根据参数 bean id ”属性的不同情况,可创建两个可能的语句。如果参数“ id ”大于 0 ,将创建下面的语句:

 

select * from ACCOUNT where ACC_ID = ?

 

或者,如果“ id ”参数小于等于 0 ,将创建下面的语句:

 

select * from ACCOUNT

 

 

1 .二元条件元素

 

二元条件元素将一个属性值和一个静态值或另一个属性值比较,如果条件为“真”,元素体的内容将被包括在查询 SQL 语句中。

 

二元条件元素的属性:

 

prepend 可被覆盖的 SQL 语句组成部分,添加在语句的前面(可选)

 

property 被比较的属性(必选)

 

compareProperty 另一个用于和前者比较的属性(必选或选择 compareValue

 

compareValue 用于比较的值(必选或选择 compareProperty

 

<isEqual>

  比较属性值和静态值或另一个属性值是否相等。

 

<isNotEqual>

  比较属性值和静态值或另一个属性值是否不相等。

 

<isGreaterThan>

  比较属性值是否大于静态值或另一个属性值。

 

<isGreaterEqual>

  比较属性值是否大于等于静态值或另一个属性值。

 

<isLessThan>

  比较属性值是否小于静态值或另一个属性值。

 

<isLessEqual>

  比较属性值是否小于等于静态值或另一个属性值。

 

例子:

 

<isLessEqual prepend=”AND” property=”age” compareValue=”18”>

 

ADOLESCENT = ‘TRUE’

 

</isLessEqual>

 

 

2 .一元条件元素

 

一元条件元素检查属性的状态是否符合特定的条件。

 

一元条件元素的属性:

 

prepend 可被覆盖的 SQL 语句组成部分,添加在语句的前面(可选)

 

property 被比较的属性(必选)

 

<isPropertyAvailable>

  检查是否存在该属性(存在 parameter bean 的属性)。

 

<isNotPropertyAvailable>

  检查是否不存在该属性(不存在 parameter bean 的属性)。

 

<isNull>

  检查属性是否为 null

 

<isNotNull>

  检查属性是否不为 null

 

<isEmpty>

  检查 Collection.size() 的值,属性的 String String.valueOf() , 是否为 null 或空(“”或 size() < 1 )。

 

<isNotEmpty>

  检查 Collection.size() 的值,属性的 String String.valueOf() , 是否不为 null 或不为空(“”或 size() > 0 )。

 

例子:

 

<isNotEmpty prepend=”AND” property=”firstName” >

 

FIRST_NAME=#firstName#

 

</isNotEmpty>

 

 

3 .其他元素

 

Parameter Present :这些元素检查参数对象是否存在。

 

Parameter Present 的属性:

 

prepend 可被覆盖的 SQL 语句组成部分,添加在语句的前面(可选)

 

<isParameterPresent>

  检查是否存在参数对象(不为 null )。

 

<isNotParameterPresent>

  检查是否不存在参数对象(参数对象为 null )。

 

例子:

 

<isNotParameterPresent prepend=”AND”>

 

EMPLOYEE_TYPE = ‘DEFAULT’

 

</isNotParameterPresent>

 

 

4 Iterate :这属性遍历整个集合,并为 List 集合中的元素重复元素体的内容。

 

Iterate 的属性:

 

prepend 可被覆盖的 SQL 语句组成部分,添加在语句的前面(可选)

 

property 类型为 java.util.List 的用于遍历的元素(必选)

 

open 整个遍历内容体开始的字符串,用于定义括号(可选)

 

close -整个遍历内容体结束的字符串,用于定义括号(可选)

 

conjunction 每次遍历内容之间的字符串,用于定义 AND OR (可选)

 

<iterate>

  遍历类型为 java.util.List 的元素。

 

例子:

 

<iterate prepend=”AND” property=”userNameList”

 

open=”(” close=”)” conjunction=”OR”>

 

username=#userNameList[]#

 

</iterate>

 

注意:使用 <iterate> 时,在 List 元素名后面包括方括号 [] 非常重要,方括号 [] 将对象标记为 List ,以防解析器简单地将 List 输出成 String

 

 

一,        注意事项

 

1. 关于特殊字符

 

因为 SQL 语句是嵌在 XML 文档中的,因此有些特殊的字符不能直接使用,例如大于号和小于号( <> )。幸运的是,解决的办法很简单,只需将包含特殊字符的 SQL 语句放在 XML CDATA 区里面就可以了。例如:

 

<statement id="getPersonsByAge" parameterClass=”int” resultClass="examples.domain.Person">

 

<![CDATA[

 

SELECT *

 

FROM PERSON

 

WHERE AGE > #value#

 

]]>

 

</statement>

 

 

 

 

 

 

 

 

2. 关于多个 SqlMap.xml id 冲突问题

 

问题描述:

 

sql-map-config 中引用多个 sqlmap.xml ,多个 sqlmap.xml 中存在相同的 statementname 的时候, ibatis 如何判断当前我准备使用哪一个 sqlmap.xml 中的 statementname 对应的 sql 语句

 

      

 

       解决方法:

 

SqlMapConfig.xml 中的 settings 标签中存在一个属性 useStatementNamespaces 当这个设定为 true 的时候,那么 iBatis 通过 SqlMap.xml namespace.id 来查找对应的 sql id ,从而避免这个问题。

 

二,        其他

 

1. 自动生成的主健

 

<insert id="insertProduct-ORACLE" parameterClass="com.domain.Product">

 

<selectKey resultClass="int" keyProperty="id" >

 

SELECT STOCKIDSEQUENCE.NEXTVAL AS ID FROM DUAL

 

</selectKey>

 

insert into PRODUCT (PRD_ID,PRD_DESCRIPTION)

 

values (#id#,#description#)

 

</insert>

 

<!— Microsoft SQL Server IDENTITY Column Example -->

 

<insert id="insertProduct-MS-SQL" parameterClass="com.domain.Product">

 

insert into PRODUCT (PRD_DESCRIPTION)

 

values (#description#)

 

<selectKey resultClass="int" keyProperty="id" >

 

SELECT @@IDENTITY AS ID

 

</selectKey>

 

</insert>

 

 

 

 

 

2. 调用存储过程

 

<parameterMap id="swapParameters" class="map" >

 

<parameter property="email1" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>

 

<parameter property="email2" jdbcType="VARCHAR" javaType="java.lang.String" mode="INOUT"/>

 

</parameterMap>

 

<procedure id="swapEmailAddresses" parameterMap="swapParameters" >

 

{call swap_email_address (?, ?)}

 

</procedure> SELECT @@IDENTITY AS ID

 

 

 

 

 

十五,    Sample

 

1.java 类,生成 iBatis 数据库操作对象

 

public class MyAppSqlConfig {

 

private static final SqlMapClient sqlMap;

 

static {

 

try {

 

String resource = “com/ibatis/example/sql-map-config.xml”;

 

Reader reader = Resources.getResourceAsReader (resource);

 

sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

 

} catch (Exception e) {

 

e.printStackTrace();

 

throw new RuntimeException (“”);

 

}

 

}

 

public static getSqlMapInstance () {

 

return sqlMap;

 

}

 

}

 

 

 

本章来源: http://blog.csdn.net/qingwaxw1980/archive/2010/02/05/5291253.aspx

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MyBatis 是一个开源的持久层框架,可以方便地将 SQL 语句和 Java 对象进行映射。如果您想要学习 MyBatis 源码,可以按照以下步骤进行: 1. 了解 MyBatis 的架构和设计原理。可以阅读官方文档和相关书籍,例如《MyBatis 技术内幕》。 2. 下载 MyBatis 的源代码,并导入到 IDE 。MyBatis 使用 Maven 进行构建,您可以使用 IDE 的 Maven 插件来下载依赖项。 3. 查看 MyBatis 的源代码结构。MyBatis 的主要代码在 `mybatis-3` 模块,包括 `src/main/java` 和 `src/main/resources` 目录。其,`src/main/java` 目录包含了 MyBatis 的核心代码,例如 `org.apache.ibatis.session.SqlSession` 类;`src/main/resources` 目录包含了 MyBatis 的配置文件和映射文件。 4. 阅读 MyBatis 的源代码。可以从 MyBatis 的入口处 `org.apache.ibatis.session.SqlSessionFactoryBuilder` 开始,深入了解 MyBatis 的初始化流程、SQL 语句的执行流程、映射文件的解析和缓存等。 5. 调试 MyBatis 的源代码。可以使用 IDE 的调试功能,对 MyBatis 进行单步调试,观察代码的执行流程,加深对 MyBatis 的理解。 6. 学习 MyBatis 的单元测试。MyBatis 的单元测试位于 `src/test/java` 目录,可以通过单元测试来了解 MyBatis 的各个功能点的使用方法和测试用例。 7. 参与 MyBatis 的开发。如果您对 MyBatis 源码有深入的了解,并希望为 MyBatis 做出贡献,可以参与 MyBatis 的开发,贡献代码和文档,提交 issue 和 PR。MyBatis 的开发社区非常活跃,可以在官方网站和 GitHub 上找到相关信息。 希望这些步骤对您学习 MyBatis 源码有所帮助。 ### 回答2: MyBatis是一个开源的Java持久层框架,通过操作对象与数据库关系映射来提供数据持久化的功能。了解MyBatis源码是学习和使用该框架的重要一步。 首先,MyBatis的源码结构比较清晰,主要分为核心模块和附属模块。核心模块包括XML配置解析、SQL语句解析、参数处理、数据库连接管理等功能的实现,是实现MyBatis基本功能的核心部分。附属模块包括缓存、事务、插件等额外功能的实现,可以根据需要进行扩展和配置。 学习MyBatis源码可以从以下几个方面入手: 1. 配置文件解析:MyBatis通过XML配置文件来进行相关的配置,了解配置文件的解析过程可以帮助理解MyBatis的初始化过程和各项配置的作用。 2. SQL语句解析与执行:MyBatis将SQL语句封装成MappedStatement对象进行管理,了解MappedStatement的生成过程,以及SQL语句的解析、参数处理和执行过程,可以深入了解MyBatis的SQL执行原理。 3. 会话管理和事务处理:MyBatis采用SqlSessionFactory和SqlSession来管理数据库连接和事务,在MyBatis源码可以学习到如何管理数据库连接池、事务的提交和回滚等核心功能的实现。 4. 缓存机制:MyBatis提供了一级缓存和二级缓存的功能,了解缓存的生成和更新过程,以及缓存的命和失效原理,可以提高数据库查询性能。 总之,通过学习MyBatis源码,可以加深对该框架的理解,掌握其内部实现原理,有助于在使用时更加灵活和高效地进行开发。同时,也为以后解决一些特殊问题提供了更多的思路和方法。 ### 回答3: MyBatis是一个优秀的持久层框架,学习其源码有助于理解其底层原理和设计思想。 首先,可以从MyBatis的入口开始学习,即SqlSessionFactoryBuilder类。该类负责解析配置文件、创建Configuration对象,并通过Configuration对象创建SqlSessionFactory实例。 接下来,可以学习Configuration类,该类负责管理整个MyBatis的配置信息。其包括了数据库连接信息、映射文件信息、缓存信息等。在该类内部,会调用XMLMapperBuilder类解析映射文件,在解析映射文件过程,会创建MappedStatement对象,该对象表示一条SQL语句的映射信息。 学习MappedStatement对象可以了解MyBatis的SQL语句解析过程。该对象包含了SQL语句的相关信息,包括参数映射关系、返回结果映射关系等。在执行SQL语句时,会使用ParameterHandler类处理参数,通过ResultSetHandler类处理查询结果。 同时,学习到Executor接口及其实现类,可以了解MyBatis的执行过程。Executor负责执行SQL语句,其包括了写操作的update方法和读操作的query方法。在执行过程,会通过StatementHandler类创建PreparedStatement对象,并通过ResultSetHandler类处理执行结果。 最后,还可以学习到MyBatis的事务处理和缓存机制。Transaction接口及其实现类负责事务管理,通过JDBC的事务机制实现了事务的提交和回滚。而Cache接口及其实现类负责缓存查询结果,在查询时会先从缓存查找结果。 总结来说,通过学习MyBatis的源码可以深入理解其底层原理和设计思想。从SqlSessionFactory的创建开始,到Configuration的配置解析、MappedStatement的创建,再到Executor的执行过程和Transaction的事务管理,以及Cache的缓存机制,逐步掌握MyBatis的各个组件和它们之间的交互关系。这对于我们使用MyBatis开发项目,解决问题和优化性能都具有积极的意义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值