25
25
<
author email =
" [email protected] " >Nan Lei</
author >
26
26
<
author email =
" [email protected] " >Dongxu Wang</
author >
27
27
<
author email =
" [email protected] " >ZeShen Lu</
author >
28
- </properties >
28
+ </properties >
29
29
30
30
<body >
31
31
<section name =" 动态 SQL" >
32
- <p >MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。</p >
33
- <p >虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。</p >
34
- <p >动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。</p >
32
+ <p >MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。</p >
33
+ <p >虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。</p >
34
+ <p >动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。</p >
35
35
<ul >
36
36
<li >if</li >
37
37
<li >choose (when, otherwise)</li >
38
38
<li >trim (where, set)</li >
39
39
<li >foreach</li >
40
40
</ul >
41
41
<subsection name =" if" id =" if" >
42
- <p >动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。比如:</p >
42
+ <p >动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。比如:</p >
43
43
<source ><![CDATA[ <select id="findActiveBlogWithTitleLike"
44
44
resultType="Blog">
45
45
SELECT * FROM BLOG
48
48
AND title like #{title}
49
49
</if>
50
50
</select>]]> </source >
51
- <p >这条语句提供了一种可选的查找文本功能。如果没有传入“title”,那么所有处于“ACTIVE”状态的BLOG都会返回;反之若传入了“title”,那么就会对“title”一列进行模糊查找并返回 BLOG 结果(细心的读者可能会发现,“title”参数值是可以包含一些掩码或通配符的)。</p >
52
- <p >如果希望通过“title”和“author”两个参数进行可选搜索该怎么办呢?首先,改变语句的名称让它更具实际意义;然后只要加入另一个条件即可。</p >
51
+ <p >这条语句提供了一种可选的查找文本功能。如果没有传入“title”,那么所有处于“ACTIVE”状态的BLOG都会返回;反之若传入了“title”,那么就会对“title”一列进行模糊查找并返回 BLOG 结果(细心的读者可能会发现,“title”参数值是可以包含一些掩码或通配符的)。</p >
52
+ <p >如果希望通过“title”和“author”两个参数进行可选搜索该怎么办呢?首先,改变语句的名称让它更具实际意义;然后只要加入另一个条件即可。</p >
53
53
<source ><![CDATA[ <select id="findActiveBlogLike"
54
54
resultType="Blog">
55
55
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
62
62
</select>]]> </source >
63
63
</subsection >
64
64
<subsection name =" choose, when, otherwise" id =" chooseWhenOtherwise" >
65
- <p >有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。</p >
66
- <p >还是上面的例子,但是这次变为提供了“title”就按“title”查找,提供了“author”就按“author”查找的情形,若两者都没有提供,就返回所有符合条件的 BLOG(实际情况可能是由管理员按一定策略选出 BLOG 列表,而不是返回大量无意义的随机结果)。</p >
65
+ <p >有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。</p >
66
+ <p >还是上面的例子,但是这次变为提供了“title”就按“title”查找,提供了“author”就按“author”查找的情形,若两者都没有提供,就返回所有符合条件的 BLOG(实际情况可能是由管理员按一定策略选出 BLOG 列表,而不是返回大量无意义的随机结果)。</p >
67
67
<source ><![CDATA[ <select id="findActiveBlogLike"
68
68
resultType="Blog">
69
69
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
96
96
AND author_name like #{author.name}
97
97
</if>
98
98
</select>]]> </source >
99
- <p >如果这些条件没有一个能匹配上会发生什么?最终这条 SQL 会变成这样:</p >
99
+ <p >如果这些条件没有一个能匹配上会发生什么?最终这条 SQL 会变成这样:</p >
100
100
<source ><![CDATA[ SELECT * FROM BLOG
101
101
WHERE]]> </source >
102
102
<p >这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样:
103
103
</p >
104
104
<source ><![CDATA[ SELECT * FROM BLOG
105
105
WHERE
106
106
AND title like ‘someTitle’]]> </source >
107
- <p >这个查询也会失败。这个问题不能简单地用条件句式来解决,如果你也曾经被迫这样写过,那么你很可能从此以后都不会再写出这种语句了。</p >
108
- <p >MyBatis 有一个简单的处理,这在 90% 的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作。一处简单的修改就能达到目的:</p >
107
+ <p >这个查询也会失败。这个问题不能简单地用条件句式来解决,如果你也曾经被迫这样写过,那么你很可能从此以后都不会再写出这种语句了。</p >
108
+ <p >MyBatis 有一个简单的处理,这在 90% 的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作。一处简单的修改就能达到目的:</p >
109
109
<source ><![CDATA[ <select id="findActiveBlogLike"
110
110
resultType="Blog">
111
111
SELECT * FROM BLOG
@@ -121,13 +121,13 @@ AND title like ‘someTitle’]]></source>
121
121
</if>
122
122
</where>
123
123
</select>]]> </source >
124
- <p ><em >where</em > 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,<em >where</em > 元素也会将它们去除。</p >
125
- <p >如果 <em >where</em > 元素没有按正常套路出牌,我们可以通过自定义 trim 元素来定制 <em >where</em > 元素的功能。比如,和 <em >where</em > 元素等价的自定义 trim 元素为:</p >
124
+ <p ><em >where</em > 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,<em >where</em > 元素也会将它们去除。</p >
125
+ <p >如果 <em >where</em > 元素没有按正常套路出牌,我们可以通过自定义 trim 元素来定制 <em >where</em > 元素的功能。比如,和 <em >where</em > 元素等价的自定义 trim 元素为:</p >
126
126
<source ><![CDATA[ <trim prefix="WHERE" prefixOverrides="AND |OR ">
127
127
...
128
128
</trim>]]> </source >
129
- <p ><em >prefixOverrides</em > 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 <em >prefixOverrides</em > 属性中的内容,并且插入 <em >prefix</em > 属性中指定的内容。</p >
130
- <p >类似的用于动态更新语句的解决方案叫做 <em >set</em >。<em >set</em > 元素可以用于动态包含需要更新的列,而舍去其它的。比如:</p >
129
+ <p ><em >prefixOverrides</em > 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 <em >prefixOverrides</em > 属性中的内容,并且插入 <em >prefix</em > 属性中指定的内容。</p >
130
+ <p >类似的用于动态更新语句的解决方案叫做 <em >set</em >。<em >set</em > 元素可以用于动态包含需要更新的列,而舍去其它的。比如:</p >
131
131
<source ><![CDATA[ <update id="updateAuthorIfNecessary">
132
132
update Author
133
133
<set>
@@ -138,15 +138,15 @@ AND title like ‘someTitle’]]></source>
138
138
</set>
139
139
where id=#{id}
140
140
</update>]]> </source >
141
- <p >这里,<em >set</em > 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。(译者注:因为用的是“if”元素,若最后一个“if”没有匹配上而前面的匹配上,SQL 语句的最后就会有一个逗号遗留)</p >
142
- <p >若你对 <em >set</em > 元素等价的自定义 trim 元素的代码感兴趣,那这就是它的真面目:</p >
141
+ <p >这里,<em >set</em > 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。(译者注:因为用的是“if”元素,若最后一个“if”没有匹配上而前面的匹配上,SQL 语句的最后就会有一个逗号遗留)</p >
142
+ <p >若你对 <em >set</em > 元素等价的自定义 trim 元素的代码感兴趣,那这就是它的真面目:</p >
143
143
<source ><![CDATA[ <trim prefix="SET" suffixOverrides=",">
144
144
...
145
145
</trim>]]> </source >
146
- <p >注意这里我们删去的是后缀值,同时添加了前缀值。</p >
146
+ <p >注意这里我们删去的是后缀值,同时添加了前缀值。</p >
147
147
</subsection >
148
148
<subsection name =" foreach" >
149
- <p >动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:</p >
149
+ <p >动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:</p >
150
150
<source ><![CDATA[ <select id="selectPostIn" resultType="domain.blog.Post">
151
151
SELECT *
152
152
FROM POST P
@@ -156,9 +156,9 @@ AND title like ‘someTitle’]]></source>
156
156
#{item}
157
157
</foreach>
158
158
</select>]]> </source >
159
- <p ><em >foreach</em > 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。</p >
160
- <p ><span class =" label important" >注意</span > 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 <em >foreach</em > 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。</p >
161
- <p >到此我们已经完成了涉及 XML 配置文件和 XML 映射文件的讨论。下一章将详细探讨 Java API,这样就能提高已创建的映射文件的利用效率。</p >
159
+ <p ><em >foreach</em > 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。</p >
160
+ <p ><span class =" label important" >注意</span > 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 <em >foreach</em > 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。</p >
161
+ <p >到此我们已经完成了涉及 XML 配置文件和 XML 映射文件的讨论。下一章将详细探讨 Java API,这样就能提高已创建的映射文件的利用效率。</p >
162
162
</subsection >
163
163
<subsection name =" bind" >
164
164
<p ><code >bind</code > 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:</p >
@@ -169,8 +169,8 @@ AND title like ‘someTitle’]]></source>
169
169
WHERE title LIKE #{pattern}
170
170
</select>]]> </source >
171
171
</subsection >
172
- <subsection name =" 多数据库支持" >
173
- <p >一个配置了“_databaseId”变量的 databaseIdProvider 可用于动态代码中,这样就可以根据不同的数据库厂商构建特定的语句。比如下面的例子:</p >
172
+ <subsection name =" 多数据库支持" >
173
+ <p >一个配置了“_databaseId”变量的 databaseIdProvider 可用于动态代码中,这样就可以根据不同的数据库厂商构建特定的语句。比如下面的例子:</p >
174
174
<source ><![CDATA[ <insert id="insert">
175
175
<selectKey keyProperty="id" resultType="int" order="BEFORE">
176
176
<if test="_databaseId == 'oracle'">
@@ -185,14 +185,14 @@ AND title like ‘someTitle’]]></source>
185
185
]]> </source >
186
186
</subsection >
187
187
<subsection name =" 动态 SQL 中的可插拔脚本语言" >
188
- <p >MyBatis 从 3.2 开始支持可插拔脚本语言,这允许你插入一种脚本语言驱动,并基于这种语言来编写动态 SQL 查询语句。</p >
189
- <p >可以通过实现以下接口来插入一种语言:</p >
188
+ <p >MyBatis 从 3.2 开始支持可插拔脚本语言,这允许你插入一种脚本语言驱动,并基于这种语言来编写动态 SQL 查询语句。</p >
189
+ <p >可以通过实现以下接口来插入一种语言:</p >
190
190
<source ><![CDATA[ public interface LanguageDriver {
191
191
ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql);
192
192
SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType);
193
193
SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType);
194
194
}]]> </source >
195
- <p >一旦设定了自定义语言驱动,你就可以在 mybatis-config.xml 文件中将它设置为默认语言:</p >
195
+ <p >一旦设定了自定义语言驱动,你就可以在 mybatis-config.xml 文件中将它设置为默认语言:</p >
196
196
<source ><![CDATA[ <typeAliases>
197
197
<typeAlias type="org.sample.MyLanguageDriver" alias="myLanguage"/>
198
198
</typeAliases>
@@ -205,7 +205,7 @@ AND title like ‘someTitle’]]></source>
205
205
<source ><![CDATA[ <select id="selectBlog" lang="myLanguage">
206
206
SELECT * FROM BLOG
207
207
</select>]]> </source >
208
- <p >或者,如果你使用的是映射器接口类,在抽象方法上加上 <code >@Lang</code > 注解即可:</p >
208
+ <p >或者,如果你使用的是映射器接口类,在抽象方法上加上 <code >@Lang</code > 注解即可:</p >
209
209
<source ><![CDATA[ public interface Mapper {
210
210
@Lang(MyLanguageDriver.class)
211
211
@Select("SELECT * FROM BLOG")
@@ -214,7 +214,7 @@ AND title like ‘someTitle’]]></source>
214
214
215
215
<p ><span class =" label important" >注意</span > 可以将 Apache Velocity 作为动态语言来使用,更多细节请参考 MyBatis-Velocity 项目。</p >
216
216
217
- <p >你前面看到的所有 xml 标签都是由默认 MyBatis 语言提供的,而它由别名为 <code >xml</code > 的语言驱动器 <code >org.apache.ibatis.scripting.xmltags.XmlLanguageDriver</code > 所提供。</p >
217
+ <p >你前面看到的所有 xml 标签都是由默认 MyBatis 语言提供的,而它由别名为 <code >xml</code > 的语言驱动器 <code >org.apache.ibatis.scripting.xmltags.XmlLanguageDriver</code > 所提供。</p >
218
218
</subsection >
219
219
</section >
220
220
</body >
0 commit comments