mybatis学习教程-3-SQL 映射 XML 文件

boredbird 2013-02-28

SQL 映射 XML 文件
MyBatis 真正强大之处就在这些映射语句,也就是它的魔力所在。对于它的强大功能,SQL 映
射文件的配置却非常简单。如果您比较SQL 映射文件配置与JDBC 代码,您很快可以发现,使用
SQL 映射文件配置可以节省 95%的代码量。MyBatis 被创建来专注于SQL,但又给您自己的实现极
大的空间。
如果 initial_context 没有配置,那么数据源就会直接从 InitialContext 进行查
找,如:
DataSource ds = (DataSource) initialContext.lookup(data_source);
MyBatis 3 - User Guide
24
SQL 映射XML 文件只有一些基本的元素需要配置,并且要按照下面的顺序来定义(in the
order that they should be defined):

cache –在特定的命名空间配置缓存。

cache-ref – 引用另外一个命名空间配置的缓存.

resultMap – 最复杂也是最强大的元素,用来描述如何从数据库结果集里加载对象。

parameterMap – 不推荐使用! 在旧的版本里使用的映射配置,这个元素在将来可能会被
删除,因此不再进行描述。

sql – 能够被其它语句重用的 SQL 块。

insert –INSERT 映射语句

update –UPDATE 映射语句

delete –DELEETE 映射语句

select –SELECT 映射语句
接下来的章节将会对每一个元素进行描述。
Select 元素
Select 是 MyBatis 中最常用的元素之一。除非您把数据取回来,否则把数据放在数据库是没
什么意义的,因此大部分的应用查询数据远多于修改数据。对每一次插入、修改、删除数据都可
能伴有大量的查询。这是 MyBatis 基本设计原则之一,也就是为什么把这么多的焦点和努力放在
查询和结果集映射上。对简单的查询,select 元素的配置是相当简单的,如:
<select id=”selectPerson” parameterType=”int” resultType=”hashmap”>
SELECT * FROM PERSON WHERE ID = #{id}
</select>
这条语句叫做 selectPerson,以 int 型(或者Integer 型)作为参数,并返回一个以数据库
列名作为键值的 HashMap。
注意这个参数的表示方法:#{id}
它告诉MyBatis 生成 PreparedStatement 参数。对于 JDBC,像这个参数会被标识为“?”,
然后传递给PreparedStatement,像这样:
// Similar JDBC code, NOT MyBatis…
String selectPerson = “SELECT * FROM PERSON WHERE ID=?”;
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);
当然,如果单独使用JDBC 去提取这个结果集并把结果集映射到对象上的话,则需要更多的代
MyBatis 3 - User Guide
25
码,而这些,MyBatis 都已经为您做到了。关于参数和结果集映射,还有许多要学的,以后有专
门的章节来讨论。
select 语句有很多的属性允许您详细配置每一条语句。
<select
id=”selectPerson”
parameterType=”int”
parameterMap=”deprecated”
resultType=”hashmap”
resultMap=”personResultMap”
flushCache=”false”
useCache=”true”
timeout=”10000”
fetchSize=”256”
statementType=”PREPARED”
resultSetType=”FORWARD_ONLY”
>
Insert、 update、 delete 元素
数据修改语句 insert、update 和 delete 的配置使用都非常相似:
<insert
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
Attribute
Description
id
在这个命名空间下唯一的标识符,可被其它语句引用
parameterType
传给此语句的参数的完整类名或别名
parameterMap
不推荐使用。这个参数将来可能被删除。
resultType
语句返回值类型的完整类名或别名。注意,如果返回的是集合
(collections),那么应该是集合所包含的具体子类型,而不是集
合本身。resultType 与 resultMap 不能同时使用
resultMap
引用的外部定义的 resultMap。结果集映射是MyBatis 中最强大的特性,同时
又非常好理解。许多复杂的映射都可以轻松解决。resultType 与 resultMap
不能同时使用
flushCache
如果设为 true,则会在每次语句调用的时候就会清空缓存。select 语句默认
设为 false
useCache
如果设为 true,则语句的结果集将被缓存,select 语句默认设为 false
timeout
设置超时时间,默认没有设置,由驱动器自己决定
fetchSize
设置从数据库获得记录的条数,默认没有设置,由驱动器自己决定
statementType
可设置为STATEMENT,PREPARED 或CALLABLE 中的任意一个,告诉MyBatis 分
别使用Statement,PreparedStatement或者CallableStatement。默认:
PREPARED
resultSetType
FORWARD_ONLY 、SCROLL_SENSITIVE 、SCROLL_INSENSITIVE 三个中的任意一
个。默认没有设置,由驱动器自己决定
MyBatis 3 - User Guide
26
statementType="PREPARED"
keyProperty=""
useGeneratedKeys=""
timeout="20000">
<update
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20000">
<delete
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20000">
下面是一些 insert、update 和 delete 语句例子。
<insert id="insertAuthor" parameterType="domain.blog.Author">
insert into Author (id,username,password,email,bio)
values (#{id},#{username},#{password},#{email},#{bio})
</insert>
<update id="updateAuthor" parameterType="domain.blog.Author">
update Author set
username = #{username},
password = #{password},
Attribute
Description
id
在这个命名空间下唯一的标识符,可被其它语句引用。
parameterType
传给此语句的参数的完整类名或别名。
parameterMap
不推荐使用,将来可能删除。
flushCache
如果设为 true,则会在每次语句调用的时候就会清空缓存。select 语句默
认设为false
timeout
设置超时时间,默认没有设置,由驱动器自己决定。
statementType
可设置为 STATEMENT,PREPARED 或 CALLABLE 中的任意一个告诉 MyBatis 分
别使用Statement,PreparedStatement 或者CallableStatement。默认:
PREPARED
useGeneratedKeys
(仅限 insert 语句时使用)告诉 MyBatis 使用 JDBC 的 getGeneratedKeys 方
法来获取数据库自动生成主键(如:MySQL、SQLSERVER 等关系型数据库会有
自增的字段)。默认:false
keyProperty
(仅限 insert 语句时使用)设置自动生成主键的字段,这个字段的值由
getGeneratedKeys 方法返回,或者由 insert 元素的 selectKey 子元素返
回。默认不设置。
MyBatis 3 - User Guide
27
email = #{email},
bio = #{bio}
where id = #{id}
</update>
<delete id="deleteAuthor” parameterType="int">
delete from Author where id = #{id}
</delete>
正如您看到,insert 元素有更多一些的扩展属性及子元素,允许您使用多种方式自动生成主
键。
首先,如果您使用的数据库支持自动生成主键(如:MySQL 和 SQL Server),那么您就可以
简单地将 useGeneratedKeys 设置为”true”,然后使用 keyProperty 设置您希望自动生成主键
的字段就可以了。例如,如果上面提到的 Author 表使用一个字段自动生成主键,那么配置语句就
可以修改为:
<insert id="insertAuthor" parameterType="domain.blog.Author"
useGeneratedKeys=”true” keyProperty=”id”>
insert into Author (username,password,email,bio)
values (#{username},#{password},#{email},#{bio})
</insert>
MyBatis 还有另外一种方式为不支持自动生成主键的数据库及 JDBC 驱动来生成键值。
下面展示一个能够随机生成ID 的例子(也许您不会这么做,这仅仅是演示 MyBatis 的功
能):
<insert id="insertAuthor" parameterType="domain.blog.Author">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
</selectKey>
insert into Author
(id, username, password, email,bio, favourite_section)
values
(#{id}, #{username}, #{password}, #{email}, #{bio},
#{favouriteSection,jdbcType=VARCHAR}
)
</insert>
在上面的例子中,selectKey 语句首先会执行,Author 表的 ID 首先会被设值,然后才会调用
insert 语句。这相当于在您的数据库中自动生成键值,不需要编写复杂的 java 代码。
selectKey 元素描述如下:
<selectKey
keyProperty="id"
resultType="int"
MyBatis 3 - User Guide
28
order="BEFORE"
statementType="PREPARED">
Sql 元素
这个元素用来定义能够被其它语句引用的可重用SQL 语句块。例如:
<sql id=”userColumns”> id,username,password </sql>
这个 SQL 语句块能够被其它语句引用,如:
<select id=”selectUsers” parameterType=”int” resultType=”hashmap”>
select <include refid=”userColumns”/>
from some_table
where id = #{id}
</select>
参数(Parameters)
在前面的语句中,我们可以看到一些例子中简单的参数(用于代入 SQL 语句中的可替换变
量,如#{id})。参数是 MyBatis 中非常强大的配置属性,基本上,90%的情况都会用到,如:
<select id=”selectUsers” parameterType=”int” resultType=”User”>
select id, username, password
from users
where id = #{id}
</select>
上面的例子演示了一个非常简单的命名参数映射,parameterType 被设置为“int”。参数可
以设置为任何类型。像基本数据类型或者像Integer 和 String 这样的简单的数据对象,(因为没
有相关属性)将使用全部参数值。而如果传递的是复杂对象(一般是指JavaBean),那情况就有
所不同。例如::
<insert id=”insertUser” parameterType=”User” >
insert into users (id, username, password)
Attribute
Description
keyProperty
设置需要自动生成键值的列。
resultType
结果类型,MyBatis 通常可以自己检测到,但这并不影响给它一个确切的类
型。MyBatis 允许使用任何基本的数据类型作为键值,也包括 String 类型。
order
可以设成 BEFORE 或者AFTER,如果设为BEFORE,那它会先选择主键,然后设
置 keyProperty,再执行 insert 语句;如果设为 AFTER,它就先执行 insert
语句再执行selectKey 语句,像数据库如 Oracle 那样在 insert 语句中调用
内嵌的序列机制一样。
statementType
像前面一样, MyBatis 支持 STATEMENT、PREPARED 和 CALLABLE 语句类型,
分别对应 Statement, PreparedStatement 和 CallableStatement 。
MyBatis 3 - User Guide
29
values (#{id}, #{username}, #{password})
</insert>
如果参数对象 User 被传递给 SQL 语句,那么将会搜寻 PreparedStatement 里的 id,username
和 password 属性,并被User 对象里相应的属性值替换。
这种传递参数到语句的方式非常优雅和简单。但参数映射还在很多特性。
首先,像 MyBatis 其它部分一样,参数可以指定许多的数据类型。
#{property,javaType=int,jdbcType=NUMERIC}
像 MyBatis 的其它部分一样,这个javaType 是由参数对象决定,除了 HashMap 以外。然后
这个 javaType 应该确保指定正确的TypeHandler 被使用。
� Note:如果传递了一个空值,那这个JDBC Type 对于所有JDBC 允许为空的列来说是必须的。
您可以研读一下关于PreparedStatement.setNull()的JavaDocs 文档。
对于需要自定义类型处理,您也可以指定一个特殊的 TypeHandler 类或者别名,如:
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
当然,这看起来更加复杂了,不过,这种情况比较少见。
对于数据类型,可以使用 numericScale 来指定小数位的长度。
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
最后,mode属性允许您指定IN、 OUT 或 INOUT 参数。如果参数是OUT 或 INOUT,参数对象
属的实际值将会改变,正如您希望调用一个输出参数。如果mode=OUT (或者 INOUT),并且
jdbcType=CURSOR (如Oracle 的REFCURSOR),您必须指定一个resultMap映射结果集给这个参数类
型。注意这里的javaType 类型是可选的,如果为空值而jdbcType =CURSOR 的话,则会自动地设
给ResultSet。
#{department,
mode=OUT,
jdbcType=CURSOR,
javaType=ResultSet,
resultMap=departmentResultMap}
MyBatis 也支持像 structs 这样高级的数据类型,但当您把 mode 设置为 out 的时候,您必须
把类型名告诉执行语句。例如:
#{middleInitial,
mode=OUT,
jdbcType=STRUCT,
jdbcTypeName=MY_TYPE,
resultMap=departmentResultMap}
MyBatis 3 - User Guide
30
尽管有这些强大的选项,但是大多数情况下您只需指定属性名,MyBatis 将会识别其它部分
的设置。最多就是给可以为null 值的列指定jdbcType:
#{firstName}
#{middleInitial,jdbcType=VARCHAR}
#{lastName}
字符串替换
默认的情况下,使用#{}语法会促使MyBatis 生成PreparedStatement并且安全地设置
PreparedStatement 参数(=?)值。尽量这是安全、快捷并且是经常使用的,但有时候您可能想
直接未更改的字符串代入到SQL 语句中。比如说,对于ORDER BY,您可以这样使用
ORDER BY ${columnName}
这样 MyBatis 就不会修改这个字符串了。
� 警告:
这种不加修改地接收用户输入并应用到语句的方式,是非常不安全的。这使用户能够
进行SQL注入,破坏代码。所以,要么这些字段不允许用户输入,要么用户每次输入后都进行检测
和规避。

相关推荐

jiong / 0评论 2020-09-17