# Mapped Statement以及属性
# Mapped Statement
命名SQL的核心概念是Mapped Statement。Mapped Statement可以使用任意的SQL语句,并支持parameterMap(输入)和resultMap(输出)。 如果只是简单情况,Mapped Statement可以使用Java类(或者数据实体)来作为parameter和result。 Mapped Statement的结构如下:
<statement id="statementName"
[parameterClass="some.class.Name"]
[resultClass="some.class.Name"]
[parameterMap="nameOfParameterMap"]
[resultMap="nameOfResultMap"]
>
select * from PRODUCT where PRD_ID = [?|#propertyName#]
order by [$simpleDynamic$]
</statement>
在上面的表达式中,括号[]里的属性是可选的属性。因此下面这个简单的例子也是正确的:
<statement id="insertTestProduct" >
insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (1, "Shih Tzu")
</statement>
上面的例子仅在需要用命名SQL来执行任意sql语句时才有作用。 常见的用法还是通过ParameterMap和ResultMap,来实现DataObject映射的特性,这是命名SQL的价值所在。
# 元素
<statement>元素是个通用声明,可以用于任何类型的SQL语句,但具体的statement类型(即<insert>、<update>、<delete>、<select>、<procedure>)提供了更直观的XML DTD,并拥有某些<statement>元素所没有的特性,因此强烈推荐使用。
下表总结了statement类型及其属性:
statement类型 | 属性 |
---|---|
<statement> | id、parameterClass、resultClass、parameterMap、resultMap |
<select> | id、parameterClass、resultClass、parameterMap、resultMap |
<procedure> | id、parameterClass、resultClass、parameterMap、resultMap |
<insert> | id、parameterClass、parameterMap |
<update> | id、parameterClass、parameterMap |
<delete> | id、parameterClass、parameterMap |
SQL显然是Mapped Statement中最重要的部分,可以使用对于数据库和JDBC Driver合法的任意SQL语句。只要JDBC Driver支持,可以使用任意的函数,甚至是多条语句。因为SQL语句是嵌在XML文档中的,因此有些特殊的字符不能直接使用,例如大于号和小于号(<>)。 幸运的是,解决的办法很简单,只需将包含特殊字符的SQL语句放在XML的CDATA区中即可。例如:
<statement id="getPersonsByAge" parameterClass="int" resultClass="commonj.sdo.DataObject">
<![CDATA[SELECT * FROM PERSON WHERE AGE > #value# ]]>
</statement>
# Mapped Statement的属性
# parameterClass
属性parameterClass的值是Java类的全限定名(即包括类的包名)。parameterClass属性虽然是可选的,但强烈建议使用,它的目的是限制输入参数的类型为指定的Java类,并优化框架的性能。如果您使用parameterMap,则没有必要使用parameterClass属性。 例如,如果想只允许Java类"commonj.sdo.DataObject"来作为输入参数,可以参考如下:
<statement id="statementName" parameterClass="commonj.sdo.DataObject">
<![CDATA[insert into PRODUCT values (#id#, #description#, #price#)]]>
</statement>
执行该命名SQL时,会使用传入的DataObject对象中属性为id、description、price的值来作为sql执行时的参数值。
# parameterMap
属性parameterMap的值等于一个预先定义的
说明:inline parameter不是Mapped Statement的属性,是一个概念,请参考Inline Parameter Map中的介绍。
parameterMap的基本思想是定义一系列有次序的参数系列,用于匹配JDBC PreparedStatement的值符号。例如:
<parameterMap id="insert-product-param" class="commonj.sdo.DataObject">
<parameter property="id"/>
<parameter property="description"/>
</parameterMap>
<statement id="insertProduct" parameterMap="insert-product-param">
<![CDATA[insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (?,?)]]>
</statement>
注意:对于使用了parameterMap作为参数的statement,写sql语句时 只能用占位符'?'。
上面的例子中,parameterMap中的两个参数按次序匹配SQL语句中的值符号(?)。因此,第一个"?"号将被"id"属性值替换,而第二个"?"号将被"description"属性值替换。<parameterMap>及其选项将在后面详细讨论。
注意:动态Mapped Statement只支持inline parameter,不支持parameterMap。
# resultClass
resultClass属性的值是Java类的全限定名(即包括类的包名)。resultClass属性可以让您指定一个Java类,根据ResultSetMetaData将其自动映射到JDBC的ResultSet。只要是属性名称和ResultSet的列名匹配,属性自动赋值给列值。这使得查询Mapped Statement变得简短。例如:
<statement id="getPerson" parameterClass="int" resultClass="commonj.sdo.DataObject">
SELECT PER_ID as id,
PER_FIRST_NAME as firstName,
PER_LAST_NAME as lastName,
PER_BIRTH_DATE as birthDate,
PER_WEIGHT_KG as weightInKilograms,
PER_HEIGHT_M as heightInMeters
FROM PERSON
WHERE PER_ID = #value#
</statement>
在上面的例子中,会返回一个Type是"com.primeton.das.datatype.AnyType"(系统默认)的DataObject。拥有的属性包括:id、firstName、lastName、birthDate、weightInKilograms和heightInMeters。每一个属性对应SQL查询语句一个列的别名(使用"as"关键字-标准的SQL语法)。一般情况下,列名和属性名称不匹配,就需要使用"as"关键字。当执行Mapped Statement时就会创建一个DataObject,从结果集中得到的列值将根据属性名和列名映射成DataObject对象的属性值。
使用resultClass的自动映射存在一些限制,无法指定输出字段的数据类型(如果需要的话),无法自动装入相关的数据(复杂属性),并且因为需要ResultSetMetaData的信息,会对性能有轻微的不利影响。但使用resultMap,这些限制都可以很容易解决。
# resultMap
属性resultMap是最常用和最重要的属性。resultMap属性的值等于预先定义的
<resultMap id="get-product-result" class="commonj.sdo.DataObject">
<result property="id" column="PRD_ID"/>
<result property="description" column="PRD_DESCRIPTION"/>
</resultMap>
<statement id="getProduct" resultMap="get-product-result">
select * from PRODUCT
</statement>
上面的例子中,通过resultMap的定义,查询语句得到的ResultSet被映射成DataObject对象。resultMap定义的"id"属性值将赋予"PRO_ID"字段值,而"description"属性值将赋予"PRD_DESCRIPTION"字段值。
- resultMap并不要求对查询出来的所有列都做映射;
- resultMap的class属性如果写commonj.sdo.DataObject,那么生成的DataObject的对象的类型是"com.primeton.das.datatype.AnyType"(系统默认),如果想生成自定义类型的DataObject,class属性就要写成自定义类型的DataObject的全限定名,如"com.primeton.Customer"。