结果映射(result map)
Result Map将从数据库查询所得的结果映射到对象的属性。在使用映射语句时,Result Map是我们要理解的最常用也是最重要的特性之一。
通过Result Map我们可以控制如何从查询结果中获取数据,以及列是如何映射到对象的属性的。Result Map可以描述列的类型、null值的替换以及复杂属性(包括集合)的映射。
扩展Result Map
可选的extends特性值可以设置为另一个Result Map的名称,这样就可以复用指定Result Map的映射方式了。“父级”Result Map的所有属性都将作为当前Result Map的一部分,“父级”Result Map的值在当前Result Map之前进行设置,其效果类似于类的继承。
提示:“父级”Result Map必须在“子级”Result Map之前定义。
<resultMap>的特性
<resultMap>接受三个特性:
特性 | 描述 |
id | 必需的,为Result Map提供唯一标识。 |
class | 可选的,指定当前Result Map使用的类。可以设置为类的完整名称或别名。 |
extends | 可选的,指定要进行“继承”的Result Map。 |
<result>元素
<resultMap>元素包含一个或多个<result>子元素,用以将执行SQL的结果集映射至对象的属性。
特性 | 描述 |
property | 必需的,表示结果对象的属性名称。 |
column | 必需的,指定结果集中的列名称,使用该列来产生当前属性。 |
columnIndex | 可选的,指定列的索引,该特性对性能会有轻微的帮助。99%的应用程序中是不需要的,而且它还会牺牲可维护性和可读性。另外一些provider中,该特性可能对性能没有任何帮助。 |
dbType | 用于显式地指定列的类型。由于CLR和数据库中类型的不一致,该特性比较有用,尤其是对datetime和string类型。 |
type | 用于显式地指定结果对象属性的CLR类型。通常属性的类型可通过反射获得,但在映射到Hashtable之类的对象时就无能为力了。 |
resultMapping | 该特性的值可以设置为另一个Result Map的名称,借助后者来填充属性。如果使用的Result Map位于另一个文件中,则必须要使用它的完全限定名称(加上命名空间)。 |
nullValue | 用于指定null值的替代值,该特性可以设置为任何有效的值(取决于属性的类型)。如果属性类型为值类型,则其值不可能为null,如果列的值为null,那么通过该特性可以将属性设定为某个常量值。另一方面,如果属性可以为null,我们可能想用某个常量值而不是null来表示它,这个时候nullValue特性也是有用的。 |
select | 用于描述对象间的关系,并自动加载复杂类型(即用户定义类型)。其值必须为另一映射语句的名称。 |
lazyLoad | 联合使用lazyLoad和select特性,可以指定select特性所指定语句的结果是否要延迟加载。延迟加载对IList和IList<>的支持是透明的,对强类型的集合类的支持则需要Castle.DynamicProxy组件。 |
typeHandler | 允许使用自定义类型处理器(Custom Type Handler)。这样就可以扩展DataMapper的能力,来处理那些provider特定的类型或者是provider不支持的类型。 |
代码示例:nullValue的使用
<resultMap id="get-product-result" class="product">
<result property="id" column="PRD_ID"/>
<result property="description" column="PRD_DESCRIPTION"/>
<result property="subCode" column="PRD_SUB_CODE" nullValue="-9999" />
</resultMap>
隐式的结果映射
如果SQL语句返回的列与结果对象的属性相匹配,那么显式的Result Map就不再必要了。在下面的例子中,列的名称和属性的名称已然匹配,因此无需声明Result Map。
<statement id="selectProduct" resultClass="Product">
select
id,
description
from PRODUCT
where id = #value#
</statement>
但是,如果列的名称和属性名称不一致,而列名不可能修改(比如使用其它公司开发的数据库),那该怎么办呢?可以使用列的别名,看下例:
<statement id="selectProduct" resultClass="Product">
select
PRD_ID as id,
PRD_DESCRIPTION as description
from PRODUCT
where PRD_ID = #value#
</statement>
当然,此时就不能指定dbType、nullValue或者其它的特性了(不要太贪心…)。