From 3e597a364684b9bb591d56d4158b50d9df729bb9 Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 12 Jan 2020 10:31:00 +0800 Subject: [PATCH 1/9] Update translations of dynamic-sql.xml --- src/site/zh/xdoc/dynamic-sql.xml | 74 ++++++++++++++++---------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/src/site/zh/xdoc/dynamic-sql.xml b/src/site/zh/xdoc/dynamic-sql.xml index 3cad7b1edab..e68fbc39b27 100644 --- a/src/site/zh/xdoc/dynamic-sql.xml +++ b/src/site/zh/xdoc/dynamic-sql.xml @@ -29,9 +29,9 @@
-

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。

-

虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。

-

动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

+

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

+

使用动态 SQL 并非一件易事,但通过提供能够被用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

+

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,那你对动态 SQL 元素会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。MyBatis 3 大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。MyBatis 采用功能强大的基于 OGNL 的表达式来替换其它大部分元素。

-

动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。比如:

+

使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分。比如:

SELECT * FROM BLOG @@ -48,8 +48,8 @@ AND title like #{title} ]]> -

这条语句提供了一种可选的查找文本功能。如果没有传入“title”,那么所有处于“ACTIVE”状态的BLOG都会返回;反之若传入了“title”,那么就会对“title”一列进行模糊查找并返回 BLOG 结果(细心的读者可能会发现,“title”参数值是可以包含一些掩码或通配符的)。

-

如果希望通过“title”和“author”两个参数进行可选搜索该怎么办呢?首先,改变语句的名称让它更具实际意义;然后只要加入另一个条件即可。

+

这条语句提供了可选的查找文本功能。如果不传入 “title”,那么所有处于 “ACTIVE” 状态的 BLOG 都会返回;如果传入了 “title” 参数,那么就会对 “title” 一列进行模糊查找并返回对应的 BLOG 结果(细心的读者可能会发现,“title” 的参数值需要包含查找掩码或通配符字符)。

+

如果希望通过 “title” 和 “author” 两个参数进行可选搜索该怎么办呢?首先,我想先将语句名称修改成更名副其实的名称;接下来,只需要加入另一个条件即可。

SELECT * FROM BLOG WHERE state = ‘ACTIVE’ @@ -61,9 +61,9 @@ ]]>
- -

有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

-

还是上面的例子,但是这次变为提供了“title”就按“title”查找,提供了“author”就按“author”查找的情形,若两者都没有提供,就返回所有符合条件的 BLOG(实际情况可能是由管理员按一定策略选出 BLOG 列表,而不是返回大量无意义的随机结果)。

+ +

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

+

还是上面的例子,但是策略变为:传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG(这可能是管理员认为,与其返回大量的无意义随机 Blog,还不如返回一些由管理员挑选的 Blog)。

SELECT * FROM BLOG WHERE state = ‘ACTIVE’ @@ -80,8 +80,8 @@ ]]>
- -

前面几个例子已经合宜地解决了一个臭名昭著的动态 SQL 问题。现在回到“if”示例,这次我们将“ACTIVE = 1”也设置成动态的条件,看看会发生什么。

+ +

前面几个例子已经合宜地解决了一个臭名昭著的动态 SQL 问题。现在回到之前的 “if” 示例,这次我们将 “state = ‘ACTIVE’” 设置成动态条件,看看会发生什么。

SELECT * FROM BLOG @@ -96,16 +96,16 @@ AND author_name like #{author.name} ]]> -

如果这些条件没有一个能匹配上会发生什么?最终这条 SQL 会变成这样:

+

如果没有匹配的条件会怎么样?最终这条 SQL 会变成这样:

-

这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样: +

这会导致查询失败。如果匹配的只是第二个条件又会怎样?这条 SQL 会是这样:

-

这个查询也会失败。这个问题不能简单地用条件句式来解决,如果你也曾经被迫这样写过,那么你很可能从此以后都不会再写出这种语句了。

-

MyBatis 有一个简单的处理,这在 90% 的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作。一处简单的修改就能达到目的:

+

这个查询也会失败。这个问题不能简单地用条件元素来解决。这个问题是如此的难以解决,以至于解决过的人不会再想碰到这种问题。

+

MyBatis 有一个简单的、在 90% 的情景下有用的解决办法。而对于无法使用这个办法的情景,你也可以对其进行自定义来解决你的问题。而这,只需要一处简单的改动:

SELECT * FROM BLOG @@ -121,13 +121,13 @@ AND title like ‘someTitle’]]> ]]> -

where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。

-

如果 where 元素没有按正常套路出牌,我们可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:

+

where 元素只会在子元素返回任何内容的情况下才去插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

+

如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:

... ]]> -

prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容。

-

类似的用于动态更新语句的解决方案叫做 setset 元素可以用于动态包含需要更新的列,而舍去其它的。比如:

+

prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格也是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。

+

用于动态更新语句的类似解决方案叫做 setset 元素可以用于动态包含需要更新的列,忽略其它不更新的列。比如:

update Author @@ -138,15 +138,15 @@ AND title like ‘someTitle’]]> where id=#{id} ]]> -

这里,set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。(译者注:因为用的是“if”元素,若最后一个“if”没有匹配上而前面的匹配上,SQL 语句的最后就会有一个逗号遗留)

-

若你对 set 元素等价的自定义 trim 元素的代码感兴趣,那这就是它的真面目:

+

这个例子中,set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。

+

来看看与 set 元素等价的自定义 trim 元素吧:

... ]]> -

注意这里我们删去的是后缀值,同时添加了前缀值。

+

注意,我们覆盖了后缀值设置,并且自定义了前缀值。

-

动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:

+

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。比如:

SELECT * FROM POST P @@ -156,9 +156,9 @@ AND title like ‘someTitle’]]> #{item} ]]> -

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。

-

注意 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

-

到此我们已经完成了涉及 XML 配置文件和 XML 映射文件的讨论。下一章将详细探讨 Java API,这样就能提高已创建的映射文件的利用效率。

+

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!

+

提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

+

至此,我们已经完成了涉及 XML 配置文件和 XML 映射文件的讨论。下一章将详细探讨 Java API,以便你能从你创建的映射配置中受益良多。

要在带注解的映射器接口类中使用动态 SQL,可以使用 script 元素。比如:

@@ -176,7 +176,7 @@ AND title like ‘someTitle’]]> void updateAuthorValues(Author author);]]>
-

bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:

+

bind 元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文。比如:

@@ -184,8 +184,8 @@ AND title like ‘someTitle’]]> WHERE title LIKE #{pattern} ]]>
- -

一个配置了“_databaseId”变量的 databaseIdProvider 可用于动态代码中,这样就可以根据不同的数据库厂商构建特定的语句。比如下面的例子:

+       +

如果配置了 databaseIdProvider,你就可以在动态代码中使用名为 “_databaseId” 的变量来为不同的数据库构建特定的语句。比如下面的例子:

@@ -199,15 +199,15 @@ AND title like ‘someTitle’]]> ]]>
- -

MyBatis 从 3.2 开始支持可插拔脚本语言,这允许你插入一种脚本语言驱动,并基于这种语言来编写动态 SQL 查询语句。

+ +

MyBatis 从 3.2 版本开始支持可插入脚本语言,这允许你插入一种语言驱动,并基于这种语言来编写动态 SQL 查询语句。

可以通过实现以下接口来插入一种语言:

parameterType); SqlSource createSqlSource(Configuration configuration, String script, Class parameterType); }]]> -

一旦设定了自定义语言驱动,你就可以在 mybatis-config.xml 文件中将它设置为默认语言:

+

实现自定义语言驱动后,你就可以在 mybatis-config.xml 文件中将它设置为默认语言:

@@ -215,21 +215,19 @@ AND title like ‘someTitle’]]> ]]> -

除了设置默认语言,你也可以针对特殊的语句指定特定语言,可以通过如下的 lang 属性来完成: +

或者,你也可以使用 lang 属性为特定的语句指定语言:

SELECT * FROM BLOG ]]> -

或者,如果你使用的是映射器接口类,在抽象方法上加上 @Lang 注解即可:

+

或者,在你的 mapper 接口上添加 @Lang 注解:

selectBlog(); }]]> - -

注意 可以将 Apache Velocity 作为动态语言来使用,更多细节请参考 MyBatis-Velocity 项目。

- -

你前面看到的所有 xml 标签都是由默认 MyBatis 语言提供的,而它由别名为 xml 的语言驱动器 org.apache.ibatis.scripting.xmltags.XmlLanguageDriver 所提供。

+

提示 可以使用 Apache Velocity 作为动态语言,更多细节请参考 MyBatis-Velocity 项目。

+

你前面看到的所有 xml 标签都由默认 MyBatis 语言提供,而它由语言驱动 org.apache.ibatis.scripting.xmltags.XmlLanguageDriver(别名为 xml)所提供。

From f8cef0d4e06632a54c0e2de0bcb3486fa3b823cc Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 28 Oct 2018 16:37:46 +0800 Subject: [PATCH 2/9] Update part of translations of java-api.xml --- src/site/site_zh.xml | 2 +- src/site/zh/xdoc/java-api.xml | 238 ++++++++++++++++------------------ 2 files changed, 113 insertions(+), 127 deletions(-) diff --git a/src/site/site_zh.xml b/src/site/site_zh.xml index 3d868162851..a8c7007e7af 100644 --- a/src/site/site_zh.xml +++ b/src/site/site_zh.xml @@ -45,7 +45,7 @@ - + diff --git a/src/site/zh/xdoc/java-api.xml b/src/site/zh/xdoc/java-api.xml index 8390e54f226..c9484a7c7e3 100644 --- a/src/site/zh/xdoc/java-api.xml +++ b/src/site/zh/xdoc/java-api.xml @@ -27,13 +27,13 @@
-

既然你已经知道如何配置 MyBatis 和创建映射文件,你就已经准备好来提升技能了。MyBatis 的 Java API 就是你收获你所做的努力的地方。正如你即将看到的,和 JDBC 相比,MyBatis 很大程度简化了你的代码并保持代码简洁,容易理解并维护。MyBatis 3 已经引入了很多重要的改进来使得 SQL 映射更加优秀。

+

既然你已经知道如何配置 MyBatis 以及如何创建映射,是时候来尝点甜头了。MyBatis 的 Java API 就是这个甜头。稍后你将看到,和 JDBC 相比,MyBatis 大幅简化了你的代码并力图保持代码简洁、容易理解和维护。为了使得 SQL 映射更加优秀,MyBatis 3 引入了许多重要的改进。

- -

在我们深入 Java API 之前,理解关于目录结构的最佳实践是很重要的。MyBatis 非常灵活,你可以用你自己的文件来做几乎所有的事情。但是对于任一框架,都有一些最佳的方式。 + +

在我们深入 Java API 之前,理解关于目录结构的最佳实践是很重要的。MyBatis 非常灵活,你可以随意安排你的文件。但和其它框架一样,目录结构有一种最佳实践。

-让我们看一下典型的应用目录结构: + 让我们看一下典型的应用目录结构:

/my_application
   /bin
@@ -42,14 +42,14 @@
   /src
     /org/myapp/
       /action
-      /data           <-- MyBatis 配置文件在这里, 包括映射器类, XML 配置, XML 映射文件。
+      /data           <-- MyBatis 配置文件在这里,包括映射器类、XML 配置、XML 映射文件。
         /mybatis-config.xml
         /BlogMapper.java
         /BlogMapper.xml
       /model
       /service
       /view
-    /properties       <-- 在你 XML 中配置的属性文件在这里。
+    /properties       <-- 在 XML 配置中出现的属性值在这里。
   /test
     /org/myapp/
       /action
@@ -61,23 +61,22 @@
   /web
     /WEB-INF
       /web.xml
-

当然这是推荐的目录结构,并非强制要求,但是使用一个通用的目录结构将更利于大家沟通。

-

这部分内容剩余的示例将假设你使用了这种目录结构。

+

当然,这是推荐的目录结构,并非强制要求,但是使用一个通用的目录结构将更有利于大家沟通。

+

本章接下来的示例将假定你遵循这种目录结构。

-

使用 MyBatis 的主要 Java 接口就是 SqlSession。你可以通过这个接口来执行命令,获取映射器和管理事务。我们会概括讨论一下 SqlSession 本身,但是首先我们还是要了解如何获取一个 SqlSession 实例。SqlSession 是由 SqlSessionFactory 实例创建的。SqlSessionFactory 对象包含创建 SqlSession 实例的所有方法。而 SqlSessionFactory 本身是由 SqlSessionFactoryBuilder 创建的,它可以从 XML、注解或手动配置 Java 代码来创建 SqlSessionFactory。

+

使用 MyBatis 的主要 Java 接口就是 SqlSession。你可以通过这个接口来执行命令,获取映射器示例和管理事务。我们稍后会介绍 SqlSession 本身,但是首先我们先来了解如何获取一个 SqlSession 实例。SqlSessions 是由 SqlSessionFactory 实例创建的。SqlSessionFactory 对象包含创建 SqlSession 实例的各种方法。而 SqlSessionFactory 本身是由 SqlSessionFactoryBuilder 创建的,它可以从 XML、注解或 Java 配置代码来创建 SqlSessionFactory。

- 注意 当 Mybatis 与一些依赖注入框架(如 Spring 或者 Guice)同时使用时,SqlSession 将被依赖注入框架所创建,所以你不需要使用 SqlSessionFactoryBuilder 或者 SqlSessionFactory,可以直接看 SqlSession 这一节。请参考 Mybatis-Spring 或者 Mybatis-Guice 手册了解更多信息。

+ 提示 当 Mybatis 与一些依赖注入框架(如 Spring 或者 Guice)同时使用时,SqlSessions 将被依赖注入框架创建并注入,所以你不需要使用 SqlSessionFactoryBuilder 或者 SqlSessionFactory,可以直接阅读 SqlSession 这一节。请参考 Mybatis-Spring 或者 Mybatis-Guice 手册以了解更多信息。

SqlSessionFactoryBuilder

-

SqlSessionFactoryBuilder 有五个 build() 方法,每一种都允许你从不同的资源中创建一个 SqlSessionFactory 实例。

+

SqlSessionFactoryBuilder 有五个 build() 方法,每一种都允许你从不同的资源中创建一个 SqlSession 实例。

SqlSessionFactory build(InputStream inputStream) SqlSessionFactory build(InputStream inputStream, String environment) SqlSessionFactory build(InputStream inputStream, Properties properties) SqlSessionFactory build(InputStream inputStream, String env, Properties props) SqlSessionFactory build(Configuration config) - -

第一种方法是最常用的,它使用了一个参照了 XML 文档或上面讨论过的更特定的 mybatis-config.xml 文件的 Reader 实例。可选的参数是 environment 和 properties。environment 决定加载哪种环境,包括数据源和事务管理器。比如:

+

第一种方法是最常用的,它接受一个指向 XML 文件(也就是之前讨论的 mybatis-config.xml 文件)的 InputStream 实例。可选的参数是 environment 和 properties。environment 决定加载哪种环境,包括数据源和事务管理器。比如:

@@ -93,28 +92,27 @@ SqlSessionFactory build(Configuration config) ... ]]> -

如果你调用了参数有 environment 的 build 方法,那么 MyBatis 将会使用 configuration 对象来配置这个 environment。当然,如果你指定了一个不合法的 environment,你就会得到错误提示。如果你调用了不带 environment 参数的 build 方法,那么就使用默认的 environment(在上面的示例中指定为 default="development" 的代码)。

-

如果你调用了参数有 properties 实例的方法,那么 MyBatis 就会加载那些 properties(属性配置文件),并在配置中可用。那些属性可以用${propName} 语法形式多次用在配置文件中。

-

回想一下,属性可以从 mybatis-config.xml 中被引用,或者直接指定它。因此理解优先级是很重要的。我们在文档前面已经提及它了,但是这里要再次重申:

+

如果你调用了带 environment 参数的 build 方法,那么 MyBatis 将使用该环境对应的配置。当然,如果你指定了一个无效的环境,会收到错误。如果你调用了不带 environment 参数的 build 方法,那么就会使用默认的环境配置(在上面的示例中,通过 default="development" 指定了默认环境)。

+ +

如果你调用了接受 properties 实例的方法,那么 MyBatis 就会加载这些属性,并在配置中提供使用。在大部分配置值中,都可以通过 ${propName} 语法形式进行使用。

+

回想一下,属性可以从 mybatis-config.xml 中被引用,或者在该文件中直接指定。因此理解优先级是很重要的。在之前的文档中,我们已经介绍过了相关内容,但为了方便查阅,这里再重新介绍一下:


-

如果一个属性存在于这些位置,那么 MyBatis 将会按照下面的顺序来加载它们:

+

如果一个属性存在于下面的多个位置,那么 MyBatis 将按照以下顺序来加载它们:

  • 首先读取在 properties 元素体中指定的属性;
  • -
  • 其次,读取从 properties 元素的类路径 resource 或 url 指定的属性,且会覆盖已经指定了的重复属性;
  • +
  • 其次,读取在 properties 元素的类路径 resource 或 url 指定的属性,且会覆盖已经指定了的重复属性;
  • 最后,读取作为方法参数传递的属性,且会覆盖已经从 properties 元素体和 resource 或 url 属性中加载了的重复属性。

因此,通过方法参数传递的属性的优先级最高,resource 或 url 指定的属性优先级中等,在 properties 元素体中指定的属性优先级最低。


- -

总结一下,前四个方法很大程度上是相同的,但是由于覆盖机制,便允许你可选地指定 environment 和/或 properties。以下给出一个从 mybatis-config.xml 文件创建 SqlSessionFactory 的示例:

+

总结一下,前四个方法很大程度上是相同的,但提供了不同的覆盖选项,允许你可选地指定 environment 和/或 properties。以下给出一个从 mybatis-config.xml 文件创建 SqlSessionFactory 的示例:

String resource = "org/mybatis/builder/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(inputStream); - -

注意到这里我们使用了 Resources 工具类,这个类在 org.apache.ibatis.io 包中。Resources 类正如其名,会帮助你从类路径下、文件系统或一个 web URL 中加载资源文件。看一下这个类的源代码或者通过你的 IDE 来查看,就会看到一整套相当实用的方法。这里给出一个简表:

+

注意到这里我们使用了 Resources 工具类,这个类在 org.apache.ibatis.io 包中。Resources 类正如其名,会帮助你从类路径下、文件系统或一个 web URL 中加载资源文件。通过快速浏览这个类的源代码或使用 IDE 进行查看,你会看到一整套相当实用的方法。这里给出一个简表:

URL getResourceURL(String resource) URL getResourceURL(ClassLoader loader, String resource) InputStream getResourceAsStream(String resource) @@ -129,8 +127,7 @@ InputStream getUrlAsStream(String urlString) Reader getUrlAsReader(String urlString) Properties getUrlAsProperties(String urlString) Class classForName(String className) - -

最后一个 build 方法的参数为 Configuration 实例。configuration 类包含你可能需要了解 SqlSessionFactory 实例的所有内容。Configuration 类对于配置的自查很有用,它包含查找和操作 SQL 映射(当应用接收请求时便不推荐使用)。作为一个 Java API 的 configuration 类具有所有配置的开关,这些你已经了解了。这里有一个简单的示例,教你如何手动配置 configuration 实例,然后将它传递给 build() 方法来创建 SqlSessionFactory。

+

最后一个 build 方法的接受一个 Configuration 实例。Configuration 类包含了对一个 SqlSessionFactory 实例你可能关心的所有内容。对于配置的检查,Configuration 类很有用,允许你查找和操纵 SQL 映射(但当应用开始接收请求时不推荐使用)。Configuration 类具有你之前学习过的所有配置的开关,只不过它们是以 Java API 形式暴露的。以下是一个简单的示例,演示如何手动配置 Configuration 实例,然后将它传递给 build() 方法来创建 SqlSessionFactory。

DataSource dataSource = BaseDataTest.createBlogDataSource(); TransactionFactory transactionFactory = new JdbcTransactionFactory(); @@ -147,15 +144,14 @@ configuration.addMapper(BoundAuthorMapper.class); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(configuration); - -

现在你就获得一个可以用来创建 SqlSession 实例的 SqlSessionFactory 了!

+

现在你就获得一个可以用来创建 SqlSession 实例的 SqlSessionFactory 了。

SqlSessionFactory

-

SqlSessionFactory 有六个方法创建 SqlSession 实例。通常来说,当你选择这些方法时你需要考虑以下几点:

+

SqlSessionFactory 有六个方法创建 SqlSession 实例。通常来说,当你选择其中一个方法时,你需要考虑以下几点:

    -
  • 事务处理:我需要在 session 使用事务或者使用自动提交功能(auto-commit)吗?(通常意味着很多数据库和/或 JDBC 驱动没有事务)
  • -
  • 连接:我需要依赖 MyBatis 获得来自数据源的配置吗?还是使用自己提供的配置?
  • -
  • 执行语句:我需要 MyBatis 复用预处理语句和/或批量更新语句(包括插入和删除)吗?
  • +
  • 事务处理:你希望在 session 作用域中使用事务作用域,还是使用自动提交(auto-commit)?(对很多数据库和/或 JDBC 驱动来说,等同于关闭事务支持)
  • +
  • 数据库连接:你希望 MyBatis 帮你从已配置的数据源获取连接,还是使用自己提供的连接?
  • +
  • 语句执行:你希望 MyBatis 复用 PreparedStatement 和/或批量更新语句(包括插入语句和删除语句)吗?

基于以上需求,有下列已重载的多个 openSession() 方法供使用。

SqlSession openSession() @@ -167,34 +163,33 @@ SqlSession openSession(ExecutorType execType) SqlSession openSession(ExecutorType execType, boolean autoCommit) SqlSession openSession(ExecutorType execType, Connection connection) Configuration getConfiguration(); - -

默认的 openSession()方法没有参数,它会创建有如下特性的 SqlSession:

+

默认的 openSession() 方法没有参数,它会创建具备如下特性的 SqlSession:

    -
  • 会开启一个事务(也就是不自动提交)。
  • -
  • 将从由当前环境配置的 DataSource 实例中获取 Connection 对象。
  • +
  • 事务作用域将会开启(也就是不自动提交)。
  • +
  • 将由当前环境配置的 DataSource 实例中获取 Connection 对象。
  • 事务隔离级别将会使用驱动或数据源的默认设置。
  • 预处理语句不会被复用,也不会批量处理更新。
-

这些方法大都是可读性强的。向 autoCommit 可选参数传递 true 值即可开启自动提交功能。若要使用自己的 Connection 实例,传递一个 Connection 实例给 connection 参数即可。注意并未覆写同时设置 ConnectionautoCommit 两者的方法,因为 MyBatis 会使用正在使用中的、设置了 Connection 的环境。MyBatis 为事务隔离级别调用使用了一个 Java 枚举包装器,称为 TransactionIsolationLevel,若不使用它,将使用 JDBC 所支持五个隔离级(NONEREAD_UNCOMMITTEDREAD_COMMITTEDREPEATABLE_READSERIALIZABLE),并按它们预期的方式来工作。

-

还有一个可能对你来说是新见到的参数,就是 ExecutorType。这个枚举类型定义了三个值: +

相信你已经能从方法签名中知道这些方法的区别。向 autoCommit 可选参数传递 true 值即可开启自动提交功能。若要使用自己的 Connection 实例,传递一个 Connection 实例给 connection 参数即可。注意没有提供同时设置 ConnectionautoCommit 的方法,这是因为 MyBatis 会使用传入的 Connection 的当前使用配置。对于事务隔离级别,MyBatis 使用了一个 Java 枚举包装器来表示,称为 TransactionIsolationLevel,事务隔离级别支持 JDBC 的五个隔离级别(NONEREAD_UNCOMMITTEDREAD_COMMITTEDREPEATABLE_READSERIALIZABLE),并且与预期的行为一致。

+

你可能对 ExecutorType 参数感到陌生。这个枚举类型定义了三个值:

    -
  • ExecutorType.SIMPLE:这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。
  • -
  • ExecutorType.REUSE:这个执行器类型会复用预处理语句。
  • -
  • ExecutorType.BATCH:这个执行器会批量执行所有更新语句,如果 SELECT 在它们中间执行,必要时请把它们区分开来以保证行为的易读性。
  • +
  • ExecutorType.SIMPLE:该类型的执行器没有特别的行为。它为每个语句的执行创建一个新的预处理语句。
  • +
  • ExecutorType.REUSE:该类型的执行器会复用预处理语句。
  • +
  • ExecutorType.BATCH:该类型的执行器会批量执行所有更新语句,如果 SELECT 在多个更新中间执行,将在必要时将多条更新语句分隔开来,以方便理解。
-

注意 在 SqlSessionFactory 中还有一个方法我们没有提及,就是 getConfiguration()。这 -个方法会返回一个 Configuration 实例,在运行时你可以使用它来自检 MyBatis 的配置。 +

提示 在 SqlSessionFactory 中还有一个方法我们没有提及,就是 getConfiguration()。这 + 个方法会返回一个 Configuration 实例,你可以在运行时使用它来检查 MyBatis 的配置。

-

注意 如果你使用的是 MyBatis 之前的版本,你要重新调用 openSession,因为旧版本的 session、事务和批量操作是分离开来的。如果使用的是新版本,那么就不必这么做了,因为它们现在都包含在 session 的作用域内了。你不必再单独处理事务或批量操作就能得到想要的全部效果。 +

提示 如果你使用过 MyBatis 的旧版本,可能还记得 session、事务和批量操作是相互独立的。在新版本中则不是这样。上述三者都包含在 session 作用域内。你不必分别处理事务或批量操作就能得到想要的全部效果。

SqlSession

-

正如上面所提到的,SqlSession 实例在 MyBatis 中是非常强大的一个类。在这里你会看到所有执行语句、提交或回滚事务和获取映射器实例的方法。

-

在 SqlSession 类中有超过 20 个方法,所以将它们组合成易于理解的分组。

+

正如上面所提到的,SqlSession 实例在 MyBatis 中是非常强大的一个类。它包含了所有执行语句、提交或回滚事务以及获取映射器实例的方法。

+

SqlSession 类的方法超过 20 个,为了方便理解,我们将它们分成几种组别。

-
执行语句方法
-

这些方法被用来执行定义在 SQL 映射的 XML 文件中的 SELECT、INSERT、UPDATE 和 DELETE 语句。它们都会自行解释,每一句都使用语句的 ID 属性和参数对象,参数可以是原生类型(自动装箱或包装类)、JavaBean、POJO 或 Map。

+
语句执行方法
+

这些方法被用来执行定义在 SQL 映射 XML 文件中的 SELECT、INSERT、UPDATE 和 DELETE 语句。你可以快速通过名字了解它们的作用,每一方法都接受语句的 ID 以及参数对象,参数可以是原生类型(支持自动装箱或包装类)、JavaBean、POJO 或 Map。

T selectOne(String statement, Object parameter) List selectList(String statement, Object parameter) Cursor selectCursor(String statement, Object parameter) @@ -202,9 +197,15 @@ Configuration getConfiguration(); int insert(String statement, Object parameter) int update(String statement, Object parameter) int delete(String statement, Object parameter)]]> -

selectOne 和 selectList 的不同仅仅是 selectOne 必须返回一个对象或 null 值。如果返回值多于一个,那么就会抛出异常。如果你不知道返回对象的数量,请使用 selectList。如果需要查看返回对象是否存在,可行的方案是返回一个值即可(0 或 1)。selectMap 稍微特殊一点,因为它会将返回的对象的其中一个属性作为 key 值,将对象作为 value 值,从而将多结果集转为 Map 类型值。因为并不是所有语句都需要参数,所以这些方法都重载成不需要参数的形式。 +

selectOne 和 selectList 的不同仅仅是 selectOne 必须返回一个对象或 null 值。如果返回值多于一个,那么就会抛出异常。如果你不知道返回对象会有多少,请使用 selectList。如果需要查看某个对象是否存在,最好的办法是查询一个 count 值(0 或 1)。selectMap 稍微特殊一点,它会将返回对象的其中一个属性作为 key 值,将对象作为 value 值,从而将多结果集转为 Map 类型值。由于并不是所有语句都需要参数,所以这些方法都具有一个不需要参数的重载形式。

-

The value returned by the insert, update and delete methods indicate the number of rows affected by the statement.

+

游标(Cursor)与列表(List)返回的结果相同,不同的是,游标借助迭代器实现了数据的惰性加载。

+ entities = session.selectCursor(statement, param)) { + for (MyEntity entity:entities) { + // process one entity + } +}]]> +

insert、update 以及 delete 方法返回的值表示受该语句影响的行数。

T selectOne(String statement) List selectList(String statement) Cursor selectCursor(String statement) @@ -212,84 +213,74 @@ int delete(String statement, Object parameter)]]> int insert(String statement) int update(String statement) int delete(String statement)]]> - -

A Cursor offers the same results as a List, except it fetches data lazily using an Iterator.

- entities = session.selectCursor(statement, param)) { - for (MyEntity entity:entities) { - // process one entity - } -}]]> - -

最后,还有 select 方法的三个高级版本,它们允许你限制返回行数的范围,或者提供自定义结果控制逻辑,这通常在数据集合庞大的情形下使用。 +

最后,还有 select 方法的三个高级版本,它们允许你限制返回行数的范围,或是提供自定义结果处理逻辑,通常在数据集非常庞大的情形下使用。

List selectList (String statement, Object parameter, RowBounds rowBounds) Cursor selectCursor(String statement, Object parameter, RowBounds rowBounds) Map selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds) void select (String statement, Object parameter, ResultHandler handler) void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler handler)]]> +

RowBounds 参数会告诉 MyBatis 略过指定数量的记录,并限制返回结果的数量。RowBounds 类有一个构造方法来接受 offset 和 limit,另外,它们是不可变的。

-

RowBounds 参数会告诉 MyBatis 略过指定数量的记录,还有限制返回结果的数量。RowBounds 类有一个构造方法来接收 offset 和 limit,另外,它们是不可二次赋值的。

int offset = 100; int limit = 25; RowBounds rowBounds = new RowBounds(offset, limit); - -

所以在这方面,不同的驱动能够取得不同级别的高效率。为了取得最佳的表现,请使用结果集的 SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 的类型(换句话说:不用 FORWARD_ONLY)。

-

ResultHandler 参数允许你按你喜欢的方式处理每一行。你可以将它添加到 List 中、创建 Map 和 Set,或者丢弃每个返回值都可以,它取代了仅保留执行语句过后的总结果列表的死板结果。你可以使用 ResultHandler 做很多事,并且这是 MyBatis 自身内部会使用的方法,以创建结果集列表。

-

Since 3.4.6, ResultHandler passed to a CALLABLE statement is used on every REFCURSOR output parameter of the stored procedure if there is any.

+

在这方面,效率取决于驱动。为了获得最佳的性能,请将 ResultSet 类型设置为 SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 的类型(换句话说:不要使用 FORWARD_ONLY)。

+

ResultHandler 参数允许你按你喜欢的方式处理每一行。你可以将它添加到 List 中、创建 Map 和 Set,甚至丢弃每个返回值,而只保留计算后的统计结果。你可以使用 ResultHandler 做很多事,这其实就是 MyBatis 构建 结果列表的内部实现办法。

+

从版本 3.4.6 开始,ResultHandler 会在存储过程的 REFCURSOR 输出参数中传递使用的 CALLABLE statement。

它的接口很简单。

+ { void handleResult(ResultContext context); }]]> - -

ResultContext 参数允许你访问结果对象本身、被创建的对象数目、以及返回值为 Boolean 的 stop 方法,你可以使用此 stop 方法来停止 MyBatis 加载更多的结果。

- +

ResultContext 参数允许你访问结果对象和当前已被创建的对象数目,另外还提供了一个返回值为 Boolean 的 stop 方法,你可以使用此 stop 方法来停止 MyBatis 加载更多的结果。

使用 ResultHandler 的时候需要注意以下两种限制:

-
    -
  • 从被 ResultHandler 调用的方法返回的数据不会被缓存。
  • -
  • 当使用结果映射集(resultMap)时,MyBatis 大多数情况下需要数行结果来构造外键对象。如果你正在使用 ResultHandler,你可以给出外键(association)或者集合(collection)尚未赋值的对象。
  • +
  • 使用带 ResultHandler 参数的方法时,收到的数据不会被缓存。
  • +
  • 当使用高级的结果映射集(resultMap)时,MyBatis 很可能需要数行结果来构造一个对象。如果你使用了 ResultHandler,你可能会接收到关联(association)或者集合(collection)尚未被填充的对象。
-
批量立即更新方法
-

有一个方法可以刷新(执行)存储在 JDBC 驱动类中的批量更新语句。当你将 ExecutorType.BATCH 作为 ExecutorType 使用时可以采用此方法。

+
立即批量更新方法
+

当你将 ExecutorType 设置为 ExecutorType.BATCH 时,可以使用这个方法刷新(执行)存储在 JDBC 驱动类中的批量更新语句。

flushStatements()]]>
事务控制方法

-控制事务作用域有四个方法。当然,如果你已经设置了自动提交或你正在使用外部事务管理器,这就没有任何效果了。然而,如果你正在使用 JDBC 事务管理器,由Connection 实例来控制,那么这四个方法就会派上用场: + 有四个方法用来控制事务作用域。当然,如果你已经设置了自动提交或你使用了外部事务管理器,这些方法就没什么作用了。然而,如果你正在使用由 Connection 实例控制的 JDBC 事务管理器,那么这四个方法就会派上用场:

void commit() void commit(boolean force) void rollback() void rollback(boolean force) -

默认情况下 MyBatis 不会自动提交事务,除非它侦测到有插入、更新或删除操作改变了数据库。如果你已经做出了一些改变而没有使用这些方法,那么你可以传递 true 值到 commit 和 rollback 方法来保证事务被正常处理(注意,在自动提交模式或者使用了外部事务管理器的情况下设置 force 值对 session 无效)。很多时候你不用调用 rollback(),因为 MyBatis 会在你没有调用 commit 时替你完成回滚操作。然而,如果你需要在支持多提交和回滚的 session 中获得更多细粒度控制,你可以使用回滚操作来达到目的。

-

注意 MyBatis-Spring 和 MyBatis-Guice 提供了声明事务处理,所以如果你在使用 Mybatis 的同时使用了Spring 或者 Guice,那么请参考它们的手册以获取更多的内容。

-
本地缓存
+

默认情况下 MyBatis 不会自动提交事务,除非它侦测到调用了插入、更新或删除方法改变了数据库。如果你没有使用这些方法提交修改,那么你可以在 commit 和 rollback 方法参数中传入 true 值,来保证事务被正常提交(注意,在自动提交模式或者使用了外部事务管理器的情况下,设置 force 值对 session 无效)。大部分情况下你无需调用 rollback(),因为 MyBatis 会在你没有调用 commit 时替你完成回滚操作。然而,如果你需要在一个可能会多次提交或回滚的 session 中获得更多细粒度控制,你可以使用回滚操作来达到目的。

+

提示 MyBatis-Spring 和 MyBatis-Guice 提供了声明事务处理,所以如果你在使用 Mybatis 的同时使用了 Spring 或者 Guice,请参考它们的手册以获取更多的内容。

+  
本地缓存

Mybatis 使用到了两种缓存:本地缓存(local cache)和二级缓存(second level cache)。

-

每当一个新 session 被创建,MyBatis 就会创建一个与之相关联的本地缓存。任何在 session 执行过的查询语句本身都会被保存在本地缓存中,那么,相同的查询语句和相同的参数所产生的更改就不会二度影响数据库了。本地缓存会被增删改、提交事务、关闭事务以及关闭 session 所清空。

-

默认情况下,本地缓存数据可在整个 session 的周期内使用,这一缓存需要被用来解决循环引用错误和加快重复嵌套查询的速度,所以它可以不被禁用掉,但是你可以设置 localCacheScope=STATEMENT 表示缓存仅在语句执行时有效。

-

注意,如果 localCacheScope 被设置为 SESSION,那么 MyBatis 所返回的引用将传递给保存在本地缓存里的相同对象。对返回的对象(例如 list)做出任何更新将会影响本地缓存的内容,进而影响存活在 session 生命周期中的缓存所返回的值。因此,不要对 MyBatis 所返回的对象作出更改,以防后患。

+

每当一个新 session 被创建,MyBatis 就会创建一个与之相关联的本地缓存。任何在 session 执行过的查询语句本身都会被保存在本地缓存中,所以,当再次执行参数相同的相同查询时,就不需要实际查询数据库了。本地缓存将会在做出修改、事务提交或回滚,以及关闭 session 时清空。

+

默认情况下,本地缓存数据的生命周期等同于整个 session 的周期。由于缓存会被用来解决循环引用问题和加快重复嵌套查询的速度,所以无法将其完全禁用。但是你可以通过设置 localCacheScope=STATEMENT 来只在语句执行时使用缓存。

+

注意,如果 localCacheScope 被设置为 SESSION,对于同一个对象,MyBatis 将返回在本地缓存中相同对象的引用。对返回的对象(例如 list)做出的任何修改将会影响本地缓存的内容,进而将会影响到在本次 session 中从缓存返回的值。因此,不要对 MyBatis 所返回的对象作出更改,以防后患。

你可以随时调用以下方法来清空本地缓存:

- void clearCache() +  void clearCache()
确保 SqlSession 被关闭
void close() -

你必须保证的最重要的事情是你要关闭所打开的任何 session。保证做到这点的最佳方式是下面的工作模式:

- try (SqlSession session = sqlSessionFactory.openSession()) { - // following 3 lines pseudocod for "doing some work" +

对于你打开的任何 session,你都要保证它们被妥善关闭,这很重要。保证妥善关闭的最佳代码模式是这样的:

+ SqlSession session = sqlSessionFactory.openSession(); +try (SqlSession session = sqlSessionFactory.openSession()) { + // 假设下面三行代码是你的业务逻辑 session.insert(...); session.update(...); session.delete(...); session.commit(); } -

注意 就像 SqlSessionFactory,你可以通过调用当前使用中的 SqlSession 的 getConfiguration 方法来获得 Configuration 实例。

+

提示 和 SqlSessionFactory 一样,你可以调用当前使用的 SqlSession 的 getConfiguration 方法来获得 Configuration 实例。

Configuration getConfiguration()
使用映射器
T getMapper(Class type)]]> -

上述的各个 insert、update、delete 和 select 方法都很强大,但也有些繁琐,可能会产生类型安全问题并且对于你的 IDE 和单元测试也没有实质性的帮助。在上面的入门章节中我们已经看到了一个使用映射器的示例。

-

因此,一个更通用的方式来执行映射语句是使用映射器类。一个映射器类就是一个仅需声明与 SqlSession 方法相匹配的方法的接口类。下面的示例展示了一些方法签名以及它们是如何映射到 SqlSession 上的。

+

上述的各个 insert、update、delete 和 select 方法都很强大,但也有些繁琐,可能会产生类型安全问题并且对于你的 IDE 和单元测试也没有实质性的帮助。在上面的入门章节中我们已经看到了一个使用映射器的示例。

+

因此,一个更通用的方式来执行映射语句是使用映射器类。一个映射器类就是一个仅需声明与 SqlSession 方法相匹配的方法的接口类。下面的示例展示了一些方法签名以及它们是如何映射到 SqlSession 上的。

// delete("deleteAuthor",5) int deleteAuthor(int id); }]]> -

总之,每个映射器方法签名应该匹配相关联的 SqlSession 方法,而字符串参数 ID 无需匹配。相反,方法名必须匹配映射语句的 ID。

-

此外,返回类型必须匹配期望的结果类型,单返回值时为所指定类的值,多返回值时为数组或集合。所有常用的类型都是支持的,包括:原生类 +

总之,每个映射器方法签名应该匹配相关联的 SqlSession 方法,而字符串参数 ID 无需匹配。相反,方法名必须匹配映射语句的 ID。

+

此外,返回类型必须匹配期望的结果类型,单返回值时为所指定类的值,多返回值时为数组或集合。所有常用的类型都是支持的,包括:原生类 型、Map、POJO 和 JavaBean。

注意 映射器接口不需要去实现任何接口或继承自任何类。只要方法可以被唯一标识对应的映射语句就可以了。

注意 映射器接口可以继承自其他接口。当使用 XML 来构建映射器接口时要保证语句被包含在合适的命名空间中。而且,唯一的限制就是你不能在两个继承关系的接口中拥有相同的方法签名(潜在的危险做法不可取)。

@@ -355,10 +346,10 @@ void rollback(boolean force) @Arg N/A -
    -
  • <arg>
  • -
  • <idArg>
  • -
+
    +
  • <arg>
  • +
  • <idArg>
  • +
单参数构造方法,是 ConstructorArgs 集合的一部分。属性有:id, column, javaType, jdbcType, typeHandler, selectresultMap。id 属性是布尔值,来标识用于比较的属性,和<idArg> XML 元素相似。Since 3.5.4, it can be used as repeatable annotation. @@ -384,10 +375,10 @@ void rollback(boolean force) @Result N/A -
    -
  • <result>
  • -
  • <id>
  • -
+
    +
  • <result>
  • +
  • <id>
  • +
在列和属性或字段之间的单独结果映射。属性有:id, column, javaType, jdbcType, typeHandler, one, many。id 属性是一个布尔值,来标识应该被用于比较(和在 XML 映射中的<id>相似)的属性。one 属性是单独的联系,和 <association> 相似,而 many 属性是对集合而言的,和<collection>相似。它们这样命名是为了避免名称冲突。Since 3.5.4, it can be used as repeatable annotation. @@ -418,41 +409,41 @@ void rollback(boolean force) -
    -
  • @Insert
  • -
  • @Update
  • -
  • @Delete
  • -
  • @Select
  • -
+
    +
  • @Insert
  • +
  • @Update
  • +
  • @Delete
  • +
  • @Select
  • +
方法 -
    -
  • <insert>
  • -
  • <update>
  • -
  • <delete>
  • -
  • <select>
  • -
+
    +
  • <insert>
  • +
  • <update>
  • +
  • <delete>
  • +
  • <select>
  • +
这四个注解分别代表将会被执行的 SQL 语句。它们用字符串数组(或单个字符串)作为参数。如果传递的是字符串数组,字符串之间先会被填充一个空格再连接成单个完整的字符串。这有效避免了以 Java 代码构建 SQL 语句时的“丢失空格”的问题。然而,你也可以提前手动连接好字符串。属性有:value,填入的值是用来组成单个 SQL 语句的字符串数组。 -
    -
  • @InsertProvider
  • -
  • @UpdateProvider
  • -
  • @DeleteProvider
  • -
  • @SelectProvider
  • -
+
    +
  • @InsertProvider
  • +
  • @UpdateProvider
  • +
  • @DeleteProvider
  • +
  • @SelectProvider
  • +
方法 -
    -
  • <insert>
  • -
  • <update>
  • -
  • <delete>
  • -
  • <select>
  • -
+
    +
  • <insert>
  • +
  • <update>
  • +
  • <delete>
  • +
  • <select>
  • +
允许构建动态 SQL。这些备选的 SQL 注解允许你指定类名和返回在运行时执行的 SQL 语句的方法。(自从MyBatis 3.4.6开始,你可以用 CharSequence 代替 String 来返回类型返回值了。)当执行映射语句的时候,MyBatis 会实例化类并执行方法,类和方法就是填入了注解的值。你可以把已经传递给映射方法了的对象作为参数,"Mapper interface type" 和 "Mapper method" and "Database ID" 会经过 ProviderContext (仅在MyBatis 3.4.5及以上支持)作为参数值。(MyBatis 3.4及以上的版本,支持多参数传入) 属性有: value, type, method。 @@ -497,21 +488,18 @@ void rollback(boolean force)
映射申明样例
-

这个例子展示了如何使用 @SelectKey 注解来在插入前读取数据库序列的值:

+

这个例子展示了如何使用 @SelectKey 注解来在插入前读取数据库序列的值:

@Insert("insert into table3 (id, name) values(#{nameId}, #{name})") @SelectKey(statement="call next value for TestSequence", keyProperty="nameId", before=true, resultType=int.class) int insertTable3(Name name); - -

这个例子展示了如何使用 @SelectKey 注解来在插入后读取数据库识别列的值:

+

这个例子展示了如何使用 @SelectKey 注解来在插入后读取数据库识别列的值:

@Insert("insert into table2 (name) values(#{name})") @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class) int insertTable2(Name name); -

这个例子展示了如何使用 @Flush 注解去调用 SqlSession#flushStatements()

flush();]]> - -

这些例子展示了如何通过指定 @Result 的 id 属性来命名结果集:

+

这些例子展示了如何通过指定 @Result 的 id 属性来命名结果集:

@Results(id = "userResult", value = { @Result(property = "id", column = "uid", id = true), @Result(property = "firstName", column = "first_name"), @@ -527,7 +515,6 @@ User getUserById(Integer id); }) @Select("select * from company where id = #{id}") Company getCompanyById(Integer id); -

这个例子展示了单一参数使用 @SqlProvider 注解:

getUsersByName(String name); @@ -544,7 +531,6 @@ class UserSqlBuilder { }}.toString(); } }]]> -

这个例子展示了多参数使用 @SqlProvider 注解:

getUsersByName( From 603b057029ba0e679e2a7827ab631d081529d87c Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sat, 17 Nov 2018 23:13:14 +0800 Subject: [PATCH 3/9] Finished updating chinese docs of java-api and statement-builders --- src/site/zh/xdoc/java-api.xml | 102 +++++++++--------- src/site/zh/xdoc/statement-builders.xml | 135 ++++++++---------------- 2 files changed, 92 insertions(+), 145 deletions(-) diff --git a/src/site/zh/xdoc/java-api.xml b/src/site/zh/xdoc/java-api.xml index c9484a7c7e3..4c01a309f2f 100644 --- a/src/site/zh/xdoc/java-api.xml +++ b/src/site/zh/xdoc/java-api.xml @@ -61,14 +61,14 @@ /web /WEB-INF /web.xml -

当然,这是推荐的目录结构,并非强制要求,但是使用一个通用的目录结构将更有利于大家沟通。

+

当然,这是推荐的目录结构,并非强制要求,但使用一个通用的目录结构将更有利于大家沟通。

本章接下来的示例将假定你遵循这种目录结构。

使用 MyBatis 的主要 Java 接口就是 SqlSession。你可以通过这个接口来执行命令,获取映射器示例和管理事务。我们稍后会介绍 SqlSession 本身,但是首先我们先来了解如何获取一个 SqlSession 实例。SqlSessions 是由 SqlSessionFactory 实例创建的。SqlSessionFactory 对象包含创建 SqlSession 实例的各种方法。而 SqlSessionFactory 本身是由 SqlSessionFactoryBuilder 创建的,它可以从 XML、注解或 Java 配置代码来创建 SqlSessionFactory。

- 提示 当 Mybatis 与一些依赖注入框架(如 Spring 或者 Guice)同时使用时,SqlSessions 将被依赖注入框架创建并注入,所以你不需要使用 SqlSessionFactoryBuilder 或者 SqlSessionFactory,可以直接阅读 SqlSession 这一节。请参考 Mybatis-Spring 或者 Mybatis-Guice 手册以了解更多信息。

+ 提示 当 Mybatis 与一些依赖注入框架(如 Spring 或者 Guice)搭配使用时,SqlSessions 将被依赖注入框架创建并注入,所以你不需要使用 SqlSessionFactoryBuilder 或者 SqlSessionFactory,可以直接阅读 SqlSession 这一节。请参考 Mybatis-Spring 或者 Mybatis-Guice 手册以了解更多信息。

SqlSessionFactoryBuilder

SqlSessionFactoryBuilder 有五个 build() 方法,每一种都允许你从不同的资源中创建一个 SqlSession 实例。

SqlSessionFactory build(InputStream inputStream) @@ -95,8 +95,8 @@ SqlSessionFactory build(Configuration config)

如果你调用了带 environment 参数的 build 方法,那么 MyBatis 将使用该环境对应的配置。当然,如果你指定了一个无效的环境,会收到错误。如果你调用了不带 environment 参数的 build 方法,那么就会使用默认的环境配置(在上面的示例中,通过 default="development" 指定了默认环境)。

如果你调用了接受 properties 实例的方法,那么 MyBatis 就会加载这些属性,并在配置中提供使用。在大部分配置值中,都可以通过 ${propName} 语法形式进行使用。

-

回想一下,属性可以从 mybatis-config.xml 中被引用,或者在该文件中直接指定。因此理解优先级是很重要的。在之前的文档中,我们已经介绍过了相关内容,但为了方便查阅,这里再重新介绍一下:

-
+

回想一下,属性不仅可以从 mybatis-config.xml 中被引用,还可以在该文件中直接指定。因此,理解属性的优先级是很重要的。在之前的文档中,我们已经介绍过了相关内容,但为了方便查阅,这里再重新介绍一下:

+

如果一个属性存在于下面的多个位置,那么 MyBatis 将按照以下顺序来加载它们:

  • 首先读取在 properties 元素体中指定的属性;
  • @@ -105,7 +105,7 @@ SqlSessionFactory build(Configuration config)

因此,通过方法参数传递的属性的优先级最高,resource 或 url 指定的属性优先级中等,在 properties 元素体中指定的属性优先级最低。

-
+

总结一下,前四个方法很大程度上是相同的,但提供了不同的覆盖选项,允许你可选地指定 environment 和/或 properties。以下给出一个从 mybatis-config.xml 文件创建 SqlSessionFactory 的示例:

String resource = "org/mybatis/builder/mybatis-config.xml"; @@ -202,7 +202,7 @@ int delete(String statement, Object parameter)]]>

游标(Cursor)与列表(List)返回的结果相同,不同的是,游标借助迭代器实现了数据的惰性加载。

entities = session.selectCursor(statement, param)) { for (MyEntity entity:entities) { - // process one entity + // 处理单个实体 } }]]>

insert、update 以及 delete 方法返回的值表示受该语句影响的行数。

@@ -245,7 +245,6 @@ public interface ResultHandler {

当你将 ExecutorType 设置为 ExecutorType.BATCH 时,可以使用这个方法刷新(执行)存储在 JDBC 驱动类中的批量更新语句。

flushStatements()]]> -
事务控制方法

有四个方法用来控制事务作用域。当然,如果你已经设置了自动提交或你使用了外部事务管理器,这些方法就没什么作用了。然而,如果你正在使用由 Connection 实例控制的 JDBC 事务管理器,那么这四个方法就会派上用场: @@ -256,7 +255,8 @@ void rollback() void rollback(boolean force)

默认情况下 MyBatis 不会自动提交事务,除非它侦测到调用了插入、更新或删除方法改变了数据库。如果你没有使用这些方法提交修改,那么你可以在 commit 和 rollback 方法参数中传入 true 值,来保证事务被正常提交(注意,在自动提交模式或者使用了外部事务管理器的情况下,设置 force 值对 session 无效)。大部分情况下你无需调用 rollback(),因为 MyBatis 会在你没有调用 commit 时替你完成回滚操作。然而,如果你需要在一个可能会多次提交或回滚的 session 中获得更多细粒度控制,你可以使用回滚操作来达到目的。

提示 MyBatis-Spring 和 MyBatis-Guice 提供了声明事务处理,所以如果你在使用 Mybatis 的同时使用了 Spring 或者 Guice,请参考它们的手册以获取更多的内容。

-  
本地缓存
+ +
本地缓存

Mybatis 使用到了两种缓存:本地缓存(local cache)和二级缓存(second level cache)。

每当一个新 session 被创建,MyBatis 就会创建一个与之相关联的本地缓存。任何在 session 执行过的查询语句本身都会被保存在本地缓存中,所以,当再次执行参数相同的相同查询时,就不需要实际查询数据库了。本地缓存将会在做出修改、事务提交或回滚,以及关闭 session 时清空。

默认情况下,本地缓存数据的生命周期等同于整个 session 的周期。由于缓存会被用来解决循环引用问题和加快重复嵌套查询的速度,所以无法将其完全禁用。但是你可以通过设置 localCacheScope=STATEMENT 来只在语句执行时使用缓存。

@@ -279,8 +279,8 @@ try (SqlSession session = sqlSessionFactory.openSession()) {
使用映射器
T getMapper(Class type)]]> -

上述的各个 insert、update、delete 和 select 方法都很强大,但也有些繁琐,可能会产生类型安全问题并且对于你的 IDE 和单元测试也没有实质性的帮助。在上面的入门章节中我们已经看到了一个使用映射器的示例。

-

因此,一个更通用的方式来执行映射语句是使用映射器类。一个映射器类就是一个仅需声明与 SqlSession 方法相匹配的方法的接口类。下面的示例展示了一些方法签名以及它们是如何映射到 SqlSession 上的。

+

上述的各个 insert、update、delete 和 select 方法都很强大,但也有些繁琐,它们并不类型安全,对你的 IDE 和单元测试也不是那么友好。因此,更常见的执行映射语句的方法是使用映射器类。

+

我们已经在之前的入门章节中见到过一个使用映射器的示例。一个映射器类就是一个仅需声明与 SqlSession 方法相匹配方法的接口类。下面的示例展示了一些方法签名以及它们是如何映射到 SqlSession 上的。

-

总之,每个映射器方法签名应该匹配相关联的 SqlSession 方法,而字符串参数 ID 无需匹配。相反,方法名必须匹配映射语句的 ID。

-

此外,返回类型必须匹配期望的结果类型,单返回值时为所指定类的值,多返回值时为数组或集合。所有常用的类型都是支持的,包括:原生类 -型、Map、POJO 和 JavaBean。

-

注意 映射器接口不需要去实现任何接口或继承自任何类。只要方法可以被唯一标识对应的映射语句就可以了。

-

注意 映射器接口可以继承自其他接口。当使用 XML 来构建映射器接口时要保证语句被包含在合适的命名空间中。而且,唯一的限制就是你不能在两个继承关系的接口中拥有相同的方法签名(潜在的危险做法不可取)。

-

你可以传递多个参数给一个映射器方法。如果你这样做了,默认情况下它们将会以 "param" 字符串紧跟着它们在参数列表中的位置来命名,比如:#{param1}、#{param2}等。如果你想改变参数的名称(只在多参数情况下),那么你可以在参数上使用 @Param("paramName") 注解。

+

总之,每个映射器方法签名应该匹配相关联的 SqlSession 方法,而字符串参数 ID 无需匹配。相反,方法名必须匹配映射语句的 ID。

+

此外,返回类型必须匹配期望的结果类型,单个返回值时为该类,多个返回值时则为数组或集合,另外也可以是游标(Cursor)。所有常用的类型都是支持的,包括:原生类型、Map、POJO 和 JavaBean。

+

提示 映射器接口不需要去实现任何接口或继承自任何类。只要方法签名可以被用来唯一识别对应的映射语句就可以了。

+

提示 映射器接口可以继承自其他接口。当使用 XML 来绑定映射器接口时,要保证语句包含在合适的命名空间中。唯一的限制是,你不能在两个具有继承关系的接口中拥有相同的方法签名(这是潜在的危险做法,不可取)。

+

你可以传递多个参数给一个映射器方法。在多个参数的情况下,默认它们将会以 param 加上它们在参数列表中的位置来命名,比如:#{param1}、#{param2}等。如果你想自定义参数的名称(只在多个参数情况下),那么你可以在参数上使用 @Param("paramName") 注解。

你也可以给方法传递一个 RowBounds 实例来限制查询结果。

-
映射器注解
-

因为最初设计时,MyBatis 是一个 XML 驱动的框架。配置信息是基于 XML 的,而且映射语句也是定义在 XML 中的。而到了 MyBatis 3,就有新选择了。MyBatis 3 构建在全面且强大的基于 Java 语言的配置 API 之上。这个配置 API 是基于 XML 的 MyBatis 配置的基础,也是新的基于注解配置的基础。注解提供了一种简单的方式来实现简单映射语句,而不会引入大量的开销。

-

注意 不幸的是,Java 注解的的表达力和灵活性十分有限。尽管很多时间都花在调查、设计和试验上,最强大的 MyBatis 映射并不能用注解来构建——并不是在开玩笑,的确是这样。比方说,C#属性就没有这些限制,因此 MyBatis.NET 将会比 XML 有更丰富的选择。也就是说,基于 Java 注解的配置离不开它的特性。

+
映射器注解
+

在最初设计时,MyBatis 是一个 XML 驱动的框架。配置信息是基于 XML 的,映射语句也是定义在 XML 中的。而在 MyBatis 3 中,我们提供了其它的配置方式。MyBatis 3 构建在全面且强大的基于 Java 语言的配置 API 之上。这个配置 API 不仅是基于 XML 的 MyBatis 配置的基础,也是新的基于注解配置的基础。注解提供了一种简单的方式来实现简单的映射语句,而不会引入大量的开销。

+

提示 不幸的是,Java 注解的表达力和灵活性十分有限。尽管我们花了很多时间在调查、设计和试验上,但最强大的 MyBatis 映射并不能用注解来构建——我们真没开玩笑。打个比方,C# 属性就没有这些限制,因此 MyBatis.NET 将会比 XML 有更丰富的选择。虽说如此,基于 Java 注解的配置还是有它的好处的。

注解如下表所示:

- + @@ -322,25 +321,25 @@ try (SqlSession session = sqlSessionFactory.openSession()) { - +         - +         - + - +         @@ -351,25 +350,25 @@ try (SqlSession session = sqlSessionFactory.openSession()) {
  • <idArg>
  • - +         - +         - +         - + @@ -380,32 +379,32 @@ try (SqlSession session = sqlSessionFactory.openSession()) {
  • <id>
  • - +         - +         - +         - + - +         - +         - +         - +         - +         - + - +         - +        
    注解 使用对象相对应的 XMLXML 等价形式 描述
    @CacheNamespace <cache>为给定的命名空间(比如类)配置缓存。属性有:implemetation, eviction, flushInterval, size, readWrite, blockingproperties为给定的命名空间(比如类)配置缓存。属性:implemetationevictionflushIntervalsizereadWriteblockingproperties
    @Property N/A <property>指定参数值或占位值(placeholder)(能被 mybatis-config.xml内的配置属性覆盖)。属性有:name, value。(仅在MyBatis 3.4.2以上版本生效)指定参数值或占位符(placeholder)(该占位符能被 mybatis-config.xml 内的配置属性替换)。属性:namevalue。(仅在 MyBatis 3.4.2 以上可用)
    @CacheNamespaceRef <cacheRef>参照另外一个命名空间的缓存来使用。属性有:value, name。如果你使用了这个注解,你应设置 value 或者 name 属性的其中一个。value 属性用于指定 Java 类型而指定命名空间(命名空间名就是指定的 Java 类型的全限定名),name 属性(这个属性仅在MyBatis 3.4.2以上版本生效)直接指定了命名空间的名字。引用另外一个命名空间的缓存以供使用。注意,即使共享相同的全限定类名,在 XML 映射文件中声明的缓存仍被识别为一个独立的命名空间。属性:valuename。如果你使用了这个注解,你应设置 value 或者 name 属性的其中一个。value 属性用于指定能够表示该命名空间的 Java 类型(命名空间名就是该 Java 类型的全限定类名),name 属性(这个属性仅在 MyBatis 3.4.2 以上可用)则直接指定了命名空间的名字。
    @ConstructorArgs 方法 <constructor>收集一组结果传递给一个结果对象的构造方法。属性有:value,它是形式参数数组。收集一组结果以传递给一个结果对象的构造方法。属性:value,它是一个 Arg 数组。
    @Arg 单参数构造方法,是 ConstructorArgs 集合的一部分。属性有:id, column, javaType, jdbcType, typeHandler, selectresultMap。id 属性是布尔值,来标识用于比较的属性,和<idArg> XML 元素相似。Since 3.5.4, it can be used as repeatable annotation.ConstructorArgs 集合的一部分,代表一个构造方法参数。属性:idcolumnjavaTypejdbcTypetypeHandlerselectresultMap。id 属性和 XML 元素 <idArg> 相似,它是一个布尔值,表示该属性是否用于唯一标识和比较对象。
    @TypeDiscriminator 方法 <discriminator>一组实例值被用来决定结果映射的表现。属性有:column, javaType, jdbcType, typeHandlercases。cases 属性是实例数组。决定使用何种结果映射的一组取值(case)。属性:columnjavaTypejdbcTypetypeHandlercases。cases 属性是一个 Case 的数组。
    @Case N/A <case>单独实例的值和它对应的映射。属性有:value, type, results。results 属性是结果数组,因此这个注解和实际的 ResultMap 很相似,由下面的 Results 注解指定。表示某个值的一个取值以及该取值对应的映射。属性:valuetyperesults。results 属性是一个 Results 的数组,因此这个注解实际上和 ResultMap 很相似,由下面的 Results 注解指定。
    @Results 方法 <resultMap>结果映射的列表,包含了一个特别结果列如何被映射到属性或字段的详情。属性有:value, id。value 属性是 Result 注解的数组。这个 id 的属性是结果映射的名称。一组结果映射,指定了对某个特定结果列,映射到某个属性或字段的方式。属性:valueid。value 属性是一个 Result 注解的数组。而 id 属性则是结果映射的名称。
    @Result 在列和属性或字段之间的单独结果映射。属性有:id, column, javaType, jdbcType, typeHandler, one, many。id 属性是一个布尔值,来标识应该被用于比较(和在 XML 映射中的<id>相似)的属性。one 属性是单独的联系,和 <association> 相似,而 many 属性是对集合而言的,和<collection>相似。它们这样命名是为了避免名称冲突。Since 3.5.4, it can be used as repeatable annotation.在列和属性或字段之间的单个结果映射。属性:idcolumnjavaTypejdbcTypetypeHandleronemany。id 属性和 XML 元素 <id> 相似,它是一个布尔值,表示该属性是否用于唯一标识和比较对象。one 属性是一个关联,和 <association> 类似,而 many 属性则是集合关联,和 <collection> 类似。这样命名是为了避免产生名称冲突。
    @One N/A <association>复杂类型的单独属性值映射。属性有:select,已映射语句(也就是映射器方法)的全限定名,它可以加载合适类型的实例。fetchType会覆盖全局的配置参数 lazyLoadingEnabled注意 联合映射在注解 API中是不支持的。这是因为 Java 注解的限制,不允许循环引用。复杂类型的单个属性映射。属性:select,指定可加载合适类型实例的映射语句(也就是映射器方法)全限定名;fetchType,指定在该映射中覆盖全局配置参数 lazyLoadingEnabled提示 注解 API 不支持联合映射。这是由于 Java 注解不允许产生循环引用。
    @Many N/A <collection>映射到复杂类型的集合属性。属性有:select,已映射语句(也就是映射器方法)的全限定名,它可以加载合适类型的实例的集合,fetchType 会覆盖全局的配置参数 lazyLoadingEnabled注意 联合映射在注解 API中是不支持的。这是因为 Java 注解的限制,不允许循环引用复杂类型的集合属性映射。属性:select,指定可加载合适类型实例集合的映射语句(也就是映射器方法)全限定名;fetchType,指定在该映射中覆盖全局配置参数 lazyLoadingEnabled提示 注解 API 不支持联合映射。这是由于 Java 注解不允许产生循环引用。
    @MapKey 方法 这是一个用在返回值为 Map 的方法上的注解。它能够将存放对象的 List 转化为 key 值为对象的某一属性的 Map。属性有: value,填入的是对象的属性名,作为 Map 的 key 值。供返回值为 Map 的方法使用的注解。它使用对象的某个属性作为 key,将对象 List 转化为 Map。属性:value,指定作为 Map 的 key 值的对象属性名。
    @Options 方法 映射语句的属性这个注解提供访问大范围的交换和配置选项的入口,它们通常在映射语句上作为属性出现。Options 注解提供了通俗易懂的方式来访问它们,而不是让每条语句注解变复杂。属性有:useCache=true, flushCache=FlushCachePolicy.DEFAULT, resultSetType=DEFAULT, statementType=PREPARED, fetchSize=-1, timeout=-1, useGeneratedKeys=false, keyProperty="", keyColumn="", resultSets=""。值得一提的是, Java 注解无法指定 null 值。因此,一旦你使用了 Options 注解,你的语句就会被上述属性的默认值所影响。要注意避免默认值带来的预期以外的行为。

    - 注意: keyColumn 属性只在某些数据库中有效(如 Oracle、PostgreSQL等)。请在插入语句一节查看更多关于 keyColumn 和 keyProperty 两者的有效值详情。
    该注解允许你指定大部分开关和配置选项,它们通常在映射语句上作为属性出现。与在注解上提供大量的属性相比,Options 注解提供了一致、清晰的方式来指定选项。属性:useCache=trueflushCache=FlushCachePolicy.DEFAULTresultSetType=DEFAULTstatementType=PREPAREDfetchSize=-1timeout=-1useGeneratedKeys=falsekeyProperty=""keyColumn=""resultSets=""。注意,Java 注解无法指定 null 值。因此,一旦你使用了 Options 注解,你的语句就会被上述属性的默认值所影响。要注意避免默认值带来的非预期行为。

    +        注意:keyColumn 属性只在某些数据库中有效(如 Oracle、PostgreSQL 等)。要了解更多关于 keyColumn 和 keyProperty 可选值信息,请查看“insert, update 和 delete”一节。
    @@ -425,7 +424,7 @@ try (SqlSession session = sqlSessionFactory.openSession()) {
  • <select>
  • 这四个注解分别代表将会被执行的 SQL 语句。它们用字符串数组(或单个字符串)作为参数。如果传递的是字符串数组,字符串之间先会被填充一个空格再连接成单个完整的字符串。这有效避免了以 Java 代码构建 SQL 语句时的“丢失空格”的问题。然而,你也可以提前手动连接好字符串。属性有:value,填入的值是用来组成单个 SQL 语句的字符串数组。每个注解分别代表将会被执行的 SQL 语句。它们用字符串数组(或单个字符串)作为参数。如果传递的是字符串数组,字符串数组会被连接成单个完整的字符串,每个字符串之间加入一个空格。这有效地避免了用 Java 代码构建 SQL 语句时产生的“丢失空格”问题。当然,你也可以提前手动连接好字符串。属性:value,指定用来组成单个 SQL 语句的字符串数组。
    @@ -445,58 +444,51 @@ try (SqlSession session = sqlSessionFactory.openSession()) {
  • <select>
  • 允许构建动态 SQL。这些备选的 SQL 注解允许你指定类名和返回在运行时执行的 SQL 语句的方法。(自从MyBatis 3.4.6开始,你可以用 CharSequence 代替 String 来返回类型返回值了。)当执行映射语句的时候,MyBatis 会实例化类并执行方法,类和方法就是填入了注解的值。你可以把已经传递给映射方法了的对象作为参数,"Mapper interface type" 和 "Mapper method" and "Database ID" 会经过 ProviderContext (仅在MyBatis 3.4.5及以上支持)作为参数值。(MyBatis 3.4及以上的版本,支持多参数传入) - 属性有: value, type, method。 - value and type 属性需填入类(The type attribute is alias for value, you must be specify either one)。 - method 需填入该类定义了的方法名 - (Since 3.5.1, you can omit method attribute, the MyBatis will resolve a target method via the - ProviderMethodResolver interface. - If not resolve by it, the MyBatis use the reserved fallback method that named provideSql)。 - 注意 接下来的小节将会讨论类,能帮助你更轻松地构建动态 SQL。允许构建动态 SQL。这些备选的 SQL 注解允许你指定返回 SQL 语句的类和方法,以供运行时执行。(从 MyBatis 3.4.6 开始,可以使用 CharSequence 代替 String 来作为返回类型)。当执行映射语句时,MyBatis 会实例化注解指定的类,并调用注解指定的方法。你可以通过 ProviderContext 传递映射方法接收到的参数、"Mapper interface type" 和 "Mapper method"(仅在 MyBatis 3.4.5 以上支持)作为参数。(MyBatis 3.4 以上支持传入多个参数)属性:typemethodtype 属性用于指定类名。method 用于指定该类的方法名。提示 接下来的“SQL 语句构建器”一章将会讨论该话题,以帮助你以更清晰、更便于阅读的方式构建动态 SQL。
    @Param 参数 N/A如果你的映射方法的形参有多个,这个注解使用在映射方法的参数上就能为它们取自定义名字。若不给出自定义名字,多参数(不包括 RowBounds 参数)则先以 "param" 作前缀,再加上它们的参数位置作为参数别名。例如 #{param1}, #{param2},这个是默认值。如果注解是 @Param("person"),那么参数就会被命名为 #{person}如果你的映射方法接受多个参数,就可以使用这个注解自定义每个参数的名字。否则在默认情况下,除 RowBounds 以外的参数会以 "param" 加参数位置被命名。例如 #{param1}, #{param2}。如果使用了 @Param("person"),参数就会被命名为 #{person}
    @SelectKey 方法 <selectKey>这个注解的功能与 <selectKey> 标签完全一致,用在已经被 @Insert@InsertProvider@Update@UpdateProvider 注解了的方法上。若在未被上述四个注解的方法上作 @SelectKey 注解则视为无效。如果你指定了 @SelectKey 注解,那么 MyBatis 就会忽略掉由 @Options 注解所设置的生成主键或设置(configuration)属性。属性有:statement 填入将会被执行的 SQL 字符串数组,keyProperty 填入将会被更新的参数对象的属性的值,before 填入 true 或 false 以指明 SQL 语句应被在插入语句的之前还是之后执行。resultType 填入 keyProperty 的 Java 类型和用 StatementPreparedStatement 和 CallableStatement 中的 STATEMENTPREPARED 或 CALLABLE 中任一值填入 statementType。默认值是 PREPARED这个注解的功能与 <selectKey> 标签完全一致。该注解只能在 @Insert@InsertProvider@Update@UpdateProvider 标注的方法上使用,否则将会被忽略。如果标注了 @SelectKey 注解,MyBatis 将会忽略掉由 @Options 注解所设置的生成主键或设置(configuration)属性。属性:statement 以字符串数组形式指定将会被执行的 SQL 语句,keyProperty 指定作为参数传入的对象对应属性的名称,该属性将会更新成新的值,before 可以指定为 true 或 false 以指明 SQL 语句应被在插入语句的之前还是之后执行。resultType 则指定 keyProperty 的 Java 类型。statementType 则用于选择语句类型,可以选择 STATEMENTPREPAREDCALLABLE 之一,它们分别对应于 StatementPreparedStatementCallableStatement。默认值是 PREPARED
    @ResultMap 方法 N/A这个注解给 @Select 或者 @SelectProvider 提供在 XML 映射中的 <resultMap> 的id。这使得注解的 select 可以复用那些定义在 XML 中的 ResultMap。如果同一 select 注解中还存在 @Results 或者 @ConstructorArgs,那么这两个注解将被此注解覆盖。这个注解为 @Select 或者 @SelectProvider 注解指定 XML 映射中 <resultMap> 元素的 id。这使得注解的 select 可以复用已在 XML 中定义的 ResultMap。如果标注的 select 注解中存在 @Results 或者 @ConstructorArgs 注解,这两个注解将被此注解覆盖。
    @ResultType 方法 N/A此注解在使用了结果处理器的情况下使用。在这种情况下,返回类型为 void,所以 Mybatis 必须有一种方式决定对象的类型,用于构造每行数据。如果有 XML 的结果映射,请使用 @ResultMap 注解。如果结果类型在 XML 的 <select> 节点中指定了,就不需要其他的注解了。其他情况下则使用此注解。比如,如果 @Select 注解在一个将使用结果处理器的方法上,那么返回类型必须是 void 并且这个注解(或者@ResultMap)必选。这个注解仅在方法返回类型是 void 的情况下生效。在使用了结果处理器的情况下,需要使用此注解。由于此时的返回类型为 void,所以 Mybatis 需要有一种方法来判断每一行返回的对象类型。如果在 XML 有对应的结果映射,请使用 @ResultMap 注解。如果结果类型在 XML 的 <select> 元素中指定了,就不需要使用其它注解了。否则就需要使用此注解。比如,如果一个标注了 @Select 的方法想要使用结果处理器,那么它的返回类型必须是 void,并且必须使用这个注解(或者 @ResultMap)。这个注解仅在方法返回类型是 void 的情况下生效。
    @Flush 方法 N/A如果使用了这个注解,定义在 Mapper 接口中的方法能够调用 SqlSession#flushStatements() 方法。(Mybatis 3.3及以上)如果使用了这个注解,定义在 Mapper 接口中的方法就能够调用 SqlSession#flushStatements() 方法。(Mybatis 3.3 以上可用)
    -
    映射申明样例
    +
    映射注解示例

    这个例子展示了如何使用 @SelectKey 注解来在插入前读取数据库序列的值:

    @Insert("insert into table3 (id, name) values(#{nameId}, #{name})") @SelectKey(statement="call next value for TestSequence", keyProperty="nameId", before=true, resultType=int.class) int insertTable3(Name name); -

    这个例子展示了如何使用 @SelectKey 注解来在插入后读取数据库识别列的值:

    +

    这个例子展示了如何使用 @SelectKey 注解来在插入后读取数据库自增列的值:

    @Insert("insert into table2 (name) values(#{name})") @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class) int insertTable2(Name name); -

    这个例子展示了如何使用 @Flush 注解去调用 SqlSession#flushStatements()

    +

    这个例子展示了如何使用 @Flush 注解来调用 SqlSession#flushStatements()

    flush();]]>

    这些例子展示了如何通过指定 @Result 的 id 属性来命名结果集:

    @@ -515,7 +507,7 @@ User getUserById(Integer id); }) @Select("select * from company where id = #{id}") Company getCompanyById(Integer id); -

    这个例子展示了单一参数使用 @SqlProvider 注解:

    +

    这个例子展示了如何使用单个参数的 @SqlProvider 注解:

    getUsersByName(String name); @@ -531,14 +523,14 @@ class UserSqlBuilder { }}.toString(); } }]]> -

    这个例子展示了多参数使用 @SqlProvider 注解:

    +

    这个例子展示了如何使用多个参数的 @SqlProvider 注解:

    getUsersByName( @Param("name") String name, @Param("orderByColumn") String orderByColumn); class UserSqlBuilder { - // If not use @Param, you should be define same arguments with mapper method + // 如果不使用 @Param,就应该定义与 mapper 方法相同的参数 public static String buildGetUsersByName( final String name, final String orderByColumn) { return new SQL(){{ @@ -549,7 +541,7 @@ class UserSqlBuilder { }}.toString(); } - // If use @Param, you can define only arguments to be used + // 如果使用 @Param,就可以只定义需要使用的参数 public static String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) { return new SQL(){{ SELECT("*"); diff --git a/src/site/zh/xdoc/statement-builders.xml b/src/site/zh/xdoc/statement-builders.xml index 7f9078f5a72..a31a2354cba 100644 --- a/src/site/zh/xdoc/statement-builders.xml +++ b/src/site/zh/xdoc/statement-builders.xml @@ -26,9 +26,9 @@ -
    +
    -

    Java程序员面对的最痛苦的事情之一就是在Java代码中嵌入SQL语句。这么来做通常是由于SQL语句需要动态来生成-否则可以将它们放到外部文件或者存储过程中。正如你已经看到的那样,MyBatis在它的XML映射特性中有一个强大的动态SQL生成方案。但有时在Java代码内部创建SQL语句也是必要的。此时,MyBatis有另外一个特性可以帮到你,在减少典型的加号,引号,新行,格式化问题和嵌入条件来处理多余的逗号或 AND 连接词之前。事实上,在Java代码中来动态生成SQL代码就是一场噩梦。例如: +

    Java 程序员面对的最痛苦的事情之一就是在 Java 代码中嵌入 SQL 语句。这通常是因为需要动态生成 SQL 语句,不然我们可以将它们放到外部文件或者存储过程中。正如你已经看到的,MyBatis 在 XML 映射功能中有一个强大的 SQL 动态生成解决方案。但有时,我们还是需要在 Java 代码里构建 SQL 语句。此时,MyBatis 有另外一个特性可以帮到你,从而让你从处理典型问题中解放出来,比如加号、引号、换行、格式化问题、嵌入条件的逗号管理及 AND 连接。确实,在 Java 代码中动态生成 SQL 代码真的就是一场噩梦。例如:

    - -

    MyBatis 3提供了方便的工具类来帮助解决该问题。使用SQL类,简单地创建一个实例来调用方法生成SQL语句。上面示例中的问题就像重写SQL类那样: + +

    MyBatis 3 提供了方便的工具类来帮助解决此问题。借助 SQL 类,我们只需要简单地创建一个实例,并调用它的方法即可生成 SQL 语句。让我们来用 SQL 类重写上面的例子:

    -

    该例中有什么特殊之处?当你仔细看时,那不用担心偶然间重复出现的"AND"关键字,或者在"WHERE"和"AND"之间的选择,抑或什么都不选。该SQL类非常注意"WHERE"应该出现在何处,哪里又应该使用"AND",还有所有的字符串链接。 +

    这个例子有什么特别的地方吗?仔细看一下你会发现,你不用担心可能会重复出现的 "AND" 关键字,或者要做出拼接 "WHERE" 还是 "AND" 还是不拼接的选择。SQL 类已经为你处理了哪里应该插入 "WHERE"、哪里应该使用 "AND" 的问题,并帮你完成所有的字符串拼接工作。

    - + -

    这里给出一些示例:

    +

    这里有一些示例:

    - 开始或插入到 - SELECT子句。 - 可以被多次调用,参数也会添加到 - SELECT子句。 - 参数通常使用逗号分隔的列名和别名列表,但也可以是数据库驱动程序接受的任意类型。 + 开始新的或追加到已有的 SELECT子句。可以被多次调用,参数会被追加到 SELECT 子句。 + 参数通常使用逗号分隔的列名和别名列表,但也可以是数据库驱动程序接受的任意参数。 @@ -179,13 +176,8 @@ public String updatePersonSql() { - 开始或插入到 - SELECT子句, - 也可以插入 - DISTINCT关键字到生成的查询语句中。 - 可以被多次调用,参数也会添加到 - SELECT子句。 - 参数通常使用逗号分隔的列名和别名列表,但也可以是数据库驱动程序接受的任意类型。 + 开始新的或追加到已有的 SELECT子句,并添加 DISTINCT 关键字到生成的查询中。可以被多次调用,参数会被追加到 SELECT 子句。 + 参数通常使用逗号分隔的列名和别名列表,但也可以是数据库驱动程序接受的任意参数。 @@ -199,11 +191,9 @@ public String updatePersonSql() { - 开始或插入到 + 开始新的或追加到已有的 FROM子句。可以被多次调用,参数会被追加到 FROM子句。 - 可以被多次调用,参数也会添加到 - FROM子句。 - 参数通常是表名或别名,也可以是数据库驱动程序接受的任意类型。 + 参数通常是一个表名或别名,也可以是数据库驱动程序接受的任意参数。 @@ -235,9 +225,8 @@ public String updatePersonSql() { - 基于调用的方法,添加新的合适类型的 - JOIN子句。 - 参数可以包含由列命和join on条件组合成标准的join。 + 基于调用的方法,添加新的合适类型的 JOIN 子句。 + 参数可以包含一个由列和连接条件构成的标准连接。 @@ -251,34 +240,23 @@ public String updatePersonSql() { - 插入新的 - WHERE子句条件, - 由AND链接。可以多次被调用,每次都由AND来链接新条件。使用 - OR() - 来分隔OR。 + 插入新的 WHERE 子句条件,并使用 AND 拼接。可以被多次调用,对于每一次调用产生的新条件,会使用 AND 拼接起来。要使用 OR 分隔,请使用 OR()OR() - 使用OR来分隔当前的 - WHERE子句条件。 - 可以被多次调用,但在一行中多次调用或生成不稳定的SQL。 + 使用 OR 来分隔当前的 WHERE 子句条件。 + 可以被多次调用,但在一行中多次调用会生成错误的 SQLAND() - 使用AND来分隔当前的 - WHERE子句条件。 - 可以被多次调用,但在一行中多次调用或生成不稳定的SQL。因为 - WHERE - 和 - HAVING - 二者都会自动链接 - AND, 这是非常罕见的方法,只是为了完整性才被使用。 + 使用 AND 来分隔当前的 WHERE子句条件。 + 可以被多次调用,但在一行中多次调用会生成错误的 SQL。由于 WHEREHAVING都会自动使用 AND 拼接, 因此这个方法并不常用,只是为了完整性才被定义出来。 @@ -292,9 +270,7 @@ public String updatePersonSql() { - 插入新的 - GROUP BY子句元素,由逗号连接。 - 可以被多次调用,每次都由逗号连接新的条件。 + 追加新的 GROUP BY 子句,使用逗号拼接。可以被多次调用,每次调用都会使用逗号将新的条件拼接起来。 @@ -308,11 +284,7 @@ public String updatePersonSql() { - 插入新的 - HAVING子句条件。 - 由AND连接。可以被多次调用,每次都由AND来连接新的条件。使用 - OR() - 来分隔OR. + 追加新的 HAVING 子句。使用 AND 拼接。可以被多次调用,每次调用都使用AND来拼接新的条件。要使用 OR 分隔,请使用 OR()。 @@ -326,9 +298,7 @@ public String updatePersonSql() { - 插入新的 - ORDER BY子句元素, - 由逗号连接。可以多次被调用,每次由逗号连接新的条件。 + 追加新的 ORDER BY 子句,使用逗号拼接。可以多次被调用,每次调用会使用逗号拼接新的条件。 @@ -403,14 +373,14 @@ public String updatePersonSql() { DELETE_FROM(String) - 开始一个delete语句并指定需要从哪个表删除的表名。通常它后面都会跟着WHERE语句! + 开始新的 delete 语句,并指定删除表的表名。通常它后面都会跟着一个 WHERE 子句! INSERT_INTO(String) - 开始一个insert语句并指定需要插入数据的表名。后面都会跟着一个或者多个VALUES() or INTO_COLUMNS() and INTO_VALUES()。 + 开始新的 insert 语句,并指定插入数据表的表名。后面应该会跟着一个或多个 VALUES() 调用,或 INTO_COLUMNS() 和 INTO_VALUES() 调用。 @@ -424,20 +394,20 @@ public String updatePersonSql() { - 针对update语句,插入到"set"列表中 + 对 update 语句追加 "set" 属性的列表 UPDATE(String) - 开始一个update语句并指定需要更新的表明。后面都会跟着一个或者多个SET(),通常也会有一个WHERE()。 + 开始新的 update 语句,并指定更新表的表名。后面都会跟着一个或多个 SET() 调用,通常也会有一个 WHERE() 调用。 VALUES(String, String) - 插入到insert语句中。第一个参数是要插入的列名,第二个参数则是该列的值。 + 追加数据值到 insert 语句中。第一个参数是数据插入的列名,第二个参数则是数据值。 @@ -445,8 +415,7 @@ public String updatePersonSql() { INTO_COLUMNS(String...) - Appends columns phrase to an insert statement. - This should be call INTO_VALUES() with together. + 追加插入列子句到 insert 语句中。应与 INTO_VALUES() 一同使用。 @@ -454,8 +423,7 @@ public String updatePersonSql() { INTO_VALUES(String...) - Appends values phrase to an insert statement. - This should be call INTO_COLUMNS() with together. + 追加插入值子句到 insert 语句中。应与 INTO_COLUMNS() 一同使用。 @@ -477,8 +445,7 @@ public String updatePersonSql() { If the target database does not support these clauses, then it is likely that using this support will create SQL that has runtime errors.

    -

    Since version 3.4.2, you can use variable-length arguments as follows:

    - +

    从版本 3.4.2 开始,你可以像下面这样使用可变长度参数:

    - 在3.2版本之前,我们使用了一点不同的做法,通过实现ThreadLocal变量来掩盖一些导致Java DSL麻烦的语言限制。但这种方式已经废弃了,现代的框架都欢迎人们使用构建器类型和匿名内部类的想法。因此,SelectBuilder 和 SqlBuilder 类都被废弃了。 + 在版本 3.2 之前,我们采取了不太一样的措施,通过使用 ThreadLocal 变量来掩盖一些对 Java DSL 不太友好的语言限制。这种方式已被废弃,在这个领域中,人们已经对现代框架使用的构建器类型和匿名内部类习以为常。因此,SelectBuilder 和 SqlBuilder 类都被废弃了。

    - 下面的方法仅仅适用于废弃的SqlBuilder 和 SelectBuilder 类。 + 下面的方法仅仅适用于废弃的 SqlBuilder 和 SelectBuilder 类。

    @@ -572,45 +539,33 @@ public String selectPersonsWithFetchFirstSql() { / RESET() - -
    这些方法清空SelectBuilder类的ThreadLocal状态,并且准备一个新的构建语句。开始新的语句时, - BEGIN()读取得最好。 - 由于一些原因(在某些条件下,也许是逻辑需要一个完全不同的语句),在执行中清理语句 - RESET()读取得最好。 + 这些方法清空 SelectBuilder 类的 ThreadLocal 状态,并准备好构建一个新的语句。开始新的语句时,BEGIN() 是最名副其实的(可读性最好的)。但如果由于一些原因(比如程序逻辑在某些条件下需要一个完全不同的语句),在执行过程中要重置语句构建状态,就很适合使用 RESET()
    SQL() 返回生成的 - SQL() - 并重置 - SelectBuilder - 状态 (好像 - BEGIN() - 或 - RESET() - 被调用了). - 因此,该方法只能被调用一次! + 该方法返回生成的 SQL() 并重置 SelectBuilder 状态(等价于调用了 BEGIN()RESET())。因此,该方法只能被调用一次!

    - SelectBuilder 和 SqlBuilder 类并不神奇,但是知道它们如何工作也是很重要的。 - SelectBuilder 使用 SqlBuilder 使用了静态导入和ThreadLocal变量的组合来开启整洁语法,可以很容易地和条件交错。使用它们,静态导入类的方法即可,就像这样(一个或其它,并非两者): + 虽然 SelectBuilder 和 SqlBuilder 类并不神奇,但是知道它们的工作原理也是很重要的。 + SelectBuilder 以及 SqlBuilder 借助静态导入和 ThreadLocal 变量实现了对插入条件友好的简洁语法。要使用它们,只需要静态导入这个类的方法即可,就像这样(只能使用其中的一条,不能同时使用):

    import static org.apache.ibatis.jdbc.SelectBuilder.*; import static org.apache.ibatis.jdbc.SqlBuilder.*; -

    这就允许像下面这样来创建方法:

    +

    然后就可以像下面这样创建一些方法:

    Date: Sun, 18 Nov 2018 10:55:49 +0800 Subject: [PATCH 4/9] Finished updating chinese doc of logging --- src/site/zh/xdoc/logging.xml | 67 +++++++++++++++++------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/src/site/zh/xdoc/logging.xml b/src/site/zh/xdoc/logging.xml index be7c5e388a5..28f9511057f 100644 --- a/src/site/zh/xdoc/logging.xml +++ b/src/site/zh/xdoc/logging.xml @@ -28,7 +28,7 @@

    -

    Mybatis 的内置日志工厂提供日志功能,内置日志工厂将日志交给以下其中一种工具作代理:

    +

    Mybatis 通过使用内置的日志工厂提供日志功能。内置日志工厂将会把日志工作委托给下面的实现之一:

    • SLF4J @@ -46,8 +46,8 @@ JDK logging
    -

    MyBatis 内置日志工厂基于运行时自省机制选择合适的日志工具。它会使用第一个查找得到的工具(按上文列举的顺序查找)。如果一个都未找到,日志功能就会被禁用。

    -

    不少应用服务器(如 Tomcat 和 WebShpere)的类路径中已经包含 Commons Logging,所以在这种配置环境下的 MyBatis 会把它作为日志工具,记住这点非常重要。这将意味着,在诸如 WebSphere 的环境中,它提供了 Commons Logging 的私有实现,你的 Log4J 配置将被忽略。MyBatis 将你的 Log4J 配置忽略掉是相当令人郁闷的(事实上,正是因为在这种配置环境下,MyBatis 才会选择使用 Commons Logging 而不是 Log4J)。如果你的应用部署在一个类路径已经包含 Commons Logging 的环境中,而你又想使用其它日志工具,你可以通过在 MyBatis 配置文件 mybatis-config.xml 里面添加一项 setting 来选择别的日志工具。

    +

    MyBatis 内置日志工厂会基于运行时检测信息选择日志委托实现。它会(按上面罗列的顺序)使用第一个查找到的实现。当没有找到这些实现时,将会禁用日志功能。

    +

    不少应用服务器(如 Tomcat 和 WebShpere)的类路径中已经包含 Commons Logging。注意,在这种配置环境下,MyBatis 会把 Commons Logging 作为日志工具。这就意味着在诸如 WebSphere 的环境中,由于提供了 Commons Logging 的私有实现,你的 Log4J 配置将被忽略。这个时候你就会感觉很郁闷:看起来 MyBatis 将你的 Log4J 配置忽略掉了(其实是因为在这种配置环境下,MyBatis 使用了 Commons Logging 作为日志实现)。如果你的应用部署在一个类路径已经包含 Commons Logging 的环境中,而你又想使用其它日志实现,你可以通过在 MyBatis 配置文件 mybatis-config.xml 里面添加一项 setting 来选择其它日志实现。

    ... @@ -56,68 +56,70 @@ ]]> -

    logImpl 可选的值有:SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING,或者是实现了接口 org.apache.ibatis.logging.Log 的,且构造方法是以字符串为参数的类的完全限定名。(译者注:可以参考org.apache.ibatis.logging.slf4j.Slf4jImpl.java的实现)

    +

    可选的值有:SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING,或者是实现了 org.apache.ibatis.logging.Log 接口,且构造方法以字符串为参数的类完全限定名。

    你也可以调用如下任一方法来使用日志工具:

    +

    你也可以调用以下任一方法来选择日志实现: -

    如果你决定要调用以上某个方法,请在调用其它 MyBatis 方法之前调用它。另外,仅当运行时类路径中存在该日志工具时,调用与该日志工具对应的方法才会生效,否则 MyBatis 一概忽略。如你环境中并不存在 Log4J,你却调用了相应的方法,MyBatis 就会忽略这一调用,转而以默认的查找顺序查找日志工具。

    +

    你应该在调用其它 MyBatis 方法之前调用以上的某个方法。另外,仅当运行时类路径中存在该日志实现时,日志实现的切换才会生效。如果你的环境中并不存在 Log4J,你却试图调用了相应的方法,MyBatis 就会忽略这一切换请求,并将以默认的查找顺序决定使用的日志实现。

    关于 SLF4J、Apache Commons Logging、Apache Log4J 和 JDK Logging 的 API 介绍不在本文档介绍范围内。不过,下面的例子可以作为一个快速入门。关于这些日志框架的更多信息,可以参考以下链接:

    +

    关于 SLF4J、Apache Commons Logging、Apache Log4J 和 JDK Logging 的 API 介绍不在本文档介绍范围内。不过,下面的例子可以作为一个快速入门。有关这些日志框架的更多信息,可以参考以下链接:

    -

    你可以对包、映射类的全限定名、命名空间或全限定语句名开启日志功能来查看 MyBatis 的日志语句。

    -

    再次说明下,具体怎么做,由使用的日志工具决定,这里以 Log4J 为例。配置日志功能非常简单:添加一个或多个配置文件(如 log4j.properties),有时需要添加 jar 包(如 log4j.jar)。下面的例子将使用 Log4J 来配置完整的日志服务,共两个步骤:

    -

    +

    你可以通过在包、映射类的全限定名、命名空间或全限定语句名上开启日志功能,来查看 MyBatis 的日志语句。 +

    再提醒一次,具体的步骤根据日志实现的不同而不同。我们接下来会以 Log4J 作为示范。配置日志功能非常简单:添加一个或多个配置文件(如 log4j.properties),有时还需要添加 jar 包(如 log4j.jar)。下面的例子将使用 Log4J 来配置完整的日志服务。一共两个步骤: +

    步骤 1:添加 Log4J 的 jar 包

    -

    因为我们使用的是 Log4J,就要确保它的 jar 包在应用中是可用的。要启用 Log4J,只要将 jar 包添加到应用的类路径中即可。Log4J 的 jar 包可以在上面的链接中下载。

    -

    对于 web 应用或企业级应用,则需要将 log4j.jar 添加到 WEB-INF/lib 目录下;对于独立应用,可以将它添加到JVM 的 -classpath 启动参数中。

    -

    +

    由于我们使用的是 Log4J,我们要确保它的 jar 包可以被应用使用。为此,需要将 jar 包添加到应用的类路径中。Log4J 的 jar 包可以在上面的链接中下载。 +

    对于 web 应用或企业级应用,你可以将 log4j.jar 添加到 WEB-INF/lib 目录下;对于独立应用,可以将它添加到 JVM 的 -classpath 启动参数中。 +

    步骤 2:配置 Log4J

    -

    配置 Log4J 比较简单,假如你需要记录这个映射器接口的日志:

    +

    配置 Log4J 比较简单。假设你需要记录这个映射器的日志: -

    在应用的类路径中创建一个名称为 log4j.properties 的文件,文件的具体内容如下:

    - 在应用的类路径中创建一个名为 log4j.properties 的文件,文件的具体内容如下: + -

    添加以上配置后,Log4J 就会记录 org.mybatis.example.BlogMapper 的详细执行操作,且仅记录应用中其它类的错误信息(若有)。

    -

    你也可以将日志的记录方式从接口级别切换到语句级别,从而实现更细粒度的控制。如下配置只对 selectBlog 语句记录日志:

    +

    上述配置将使 Log4J 详细打印 org.mybatis.example.BlogMapper 的日志,对于应用的其它部分,只打印错误信息。

    +

    为了实现更细粒度的日志输出,你也可以只打印特定语句的日志。以下配置将只打印语句 selectBlog 的日志: log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE - -

    与此相对,可以对一组映射器接口记录日志,只要对映射器接口所在的包开启日志功能即可:

    +

    或者,你也可以打印一组映射器的日志,只需要打开映射器所在的包的日志功能即可:

    log4j.logger.org.mybatis.example=TRACE - -

    某些查询可能会返回庞大的结果集,此时只想记录其执行的 SQL 语句而不想记录结果该怎么办?为此,Mybatis 中 SQL 语句的日志级别被设为DEBUG(JDK 日志设为 FINE),结果的日志级别为 TRACE(JDK 日志设为 FINER)。所以,只要将日志级别调整为 DEBUG 即可达到目的:

    +

    某些查询可能会返回庞大的结果集。这时,你可能只想查看 SQL 语句,而忽略返回的结果集。为此,SQL 语句将会在 DEBUG 日志级别下记录(JDK 日志则为 FINE)。返回的结果集则会在 TRACE 日志级别下记录(JDK 日志则为 FINER)。因此,只要将日志级别调整为 DEBUG 即可: log4j.logger.org.mybatis.example=DEBUG - -

    要记录日志的是类似下面的映射器文件而不是映射器接口又该怎么做呢?

    +

    但如果你要为下面的映射器 XML 文件打印日志,又该怎么办呢? select * from Blog where id = #{id} ]]> - -

    如需对 XML 文件记录日志,只要对命名空间增加日志记录功能即可:

    +

    这时,你可以通过打开命名空间的日志功能来对整个 XML 记录日志: log4j.logger.org.mybatis.example.BlogMapper=TRACE - -

    要记录具体语句的日志可以这样做:

    +

    而要记录具体语句的日志,可以这样做:

    log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE - -

    你应该注意到了,为映射器接口和 XML 文件添加日志功能的语句毫无差别。

    - -

    注意 如果你使用的是 SLF4J 或 Log4j 2,MyBatis 将以 MYBATIS 这个值进行调用。

    - -

    配置文件 log4j.properties 的余下内容是针对日志输出源的,这一内容已经超出本文档范围。关于 Log4J 的更多内容,可以参考Log4J 的网站。不过,你也可以简单地做做实验,看看不同的配置会产生怎样的效果。

    +

    你应该会发现,为映射器和 XML 文件打开日志功能的语句毫无差别。 +

    提示 如果你使用的是 SLF4J 或 Log4j 2,MyBatis 将以 MYBATIS 这个标记值进行调用。

    +

    配置文件 log4j.properties 的余下内容用来配置输出器(appender),这一内容已经超出本文档的范围。关于 Log4J 的更多内容,可以参考上面的 Log4J 网站。或者,你也可以简单地做个实验,看看不同的配置会产生怎样的效果。

    From eb86c3439f97df1926097efbe8e22075b184a0dd Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 31 Mar 2019 01:12:41 +0800 Subject: [PATCH 5/9] Polish documents(old) --- src/site/zh/xdoc/configuration.xml | 201 ++++++++++++------------ src/site/zh/xdoc/getting-started.xml | 55 +++---- src/site/zh/xdoc/index.xml | 10 +- src/site/zh/xdoc/sqlmap-xml.xml | 102 ++++++------ src/site/zh/xdoc/statement-builders.xml | 6 +- 5 files changed, 187 insertions(+), 187 deletions(-) diff --git a/src/site/zh/xdoc/configuration.xml b/src/site/zh/xdoc/configuration.xml index 1ee980bac70..8f51b45e9a0 100644 --- a/src/site/zh/xdoc/configuration.xml +++ b/src/site/zh/xdoc/configuration.xml @@ -73,7 +73,7 @@ ]]>

    这个例子中的 username 和 password 将会由 properties 元素中设置的相应值来替换。 driver 和 url 属性将会由 config.properties 文件中对应的值来替换。这样就为配置提供了诸多灵活选择。

    -

    属性也可以被传递到 SqlSessionFactoryBuilder.build()方法中。例如:

    +

    也可以在 SqlSessionFactoryBuilder.build() 方法中传入属性。例如:

    如果属性在不只一个地方进行了配置,那么 MyBatis 将按照下面的顺序来加载:

      -
    • 在 properties 元素体内指定的属性首先被读取。 +
    • 首先读取在 properties 元素体内指定的属性。
    • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件或根据 url 属性指定的路径读取属性文件,并覆盖已读取的同名属性。 @@ -91,7 +91,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ

    因此,通过方法参数传递的属性具有最高优先级,resource/url - 属性中指定的配置文件次之,最低优先级的是 properties 属性中指定的属性。

    + 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。

    从 MyBatis 3.4.2 开始,你可以为占位符指定一个默认值。例如: @@ -104,7 +104,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ

    这个特性默认是关闭的。如果你想为占位符指定一个默认值, - 你应该添加一个指定的属性来开启这个特性。例如: + 你应该添加一个特定的属性来开启这个特性。例如:

    这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 - 下表描述了设置中各项的意图、默认值等。

    + 下表描述了设置中各项设置的含义、默认值等。

    @@ -151,7 +151,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ cacheEnabled
    - 全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。 + 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false @@ -181,8 +181,8 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ aggressiveLazyLoading - 当开启时,任何方法的调用都会加载该对象的所有属性。 - 否则,每个属性会按需加载(参考 lazyLoadTriggerMethods)。 + 当开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 + 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。 true | false @@ -196,7 +196,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ multipleResultSetsEnabled - 是否允许单一语句返回多结果集(需要驱动支持)。 + 是否允许单个语句返回多结果集(需要驱动支持)。 true | false @@ -210,7 +210,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ useColumnLabel - 使用列标签代替列名。不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。 + 使用列标签代替列名。不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察使用驱动的结果。 true | false @@ -224,8 +224,8 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ useGeneratedKeys - 允许 JDBC 支持自动生成主键,需要驱动支持。 - 如果设置为 true 则这个设置强制使用自动生成主键,尽管一些驱动不能支持但仍可正常工作(比如 Derby)。 + 允许 JDBC 支持自动生成主键,需要驱动支持。如果设置为 + true,将强制使用自动生成主键。尽管一些驱动不支持此特性,但仍可正常工作(如 Derby)。 true | false @@ -240,7 +240,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ 指定 MyBatis 应如何自动映射列到字段或属性。 - NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果集映射的结果集。 + NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任意复杂的结果集(无论是否嵌套)。 @@ -276,7 +276,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ defaultExecutorType - 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared statements); + 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器将重用语句并执行批量更新。 @@ -307,7 +307,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ defaultFetchSize - 为驱动的结果集获取数量(fetchSize)设置一个提示值。此参数只可以在查询设置中被覆盖。 + 为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。 任意正整数 @@ -335,7 +335,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ safeRowBoundsEnabled - 允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 + 是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 true | false @@ -349,7 +349,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ safeResultHandlerEnabled - 允许在嵌套语句中使用分页(ResultHandler)。如果允许使用则设置为 false。 + 是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。 true | false @@ -363,8 +363,8 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ mapUnderscoreToCamelCase - 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 - A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 + 是否开启驼峰命名自动映射,即从经典数据库列名 + A_COLUMN 映射到经典 Java 属性名 aColumn。 true | false @@ -378,9 +378,9 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ localCacheScope - MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 - 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 - 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 + MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 + 默认值为 SESSION,会缓存一个会话中执行的所有查询。 + 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。 SESSION | STATEMENT @@ -394,7 +394,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ jdbcTypeForNull - 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 + 当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 @@ -409,7 +409,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ lazyLoadTriggerMethods - 指定哪个对象的方法触发一次延迟加载。 + 指定对象的哪些方法触发一次延迟加载。 用逗号分隔的方法列表。 @@ -423,7 +423,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ defaultScriptingLanguage - 指定动态 SQL 生成的默认语言。 + 指定动态 SQL 生成使用的默认脚本语言。 一个类型别名或完全限定类名。 @@ -559,7 +559,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3) - 类型别名或者全类名. + 一个类型别名或完全限定类名。 未设置 @@ -590,8 +590,8 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ -

    类型别名是为 Java 类型设置一个短的名字。 - 它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。例如:

    +

    类型别名可为 Java 类型设置一个缩写名字。 + 它只和 XML 配置有关,存在的意义仅在于减少全限定类名的冗余。例如:

    @@ -850,8 +850,8 @@ public class Author {
    -

    无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, - 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。

    +

    MyBatis 在设置预处理语句(PreparedStatement)中的参数或在结果集中取出一个值时, + 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。

    提示 从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API) 。 @@ -1282,10 +1282,10 @@ public class Author {

    - 你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 + 你可以重写已有的类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, - 然后可以选择性地将它映射到一个 JDBC 类型。比如: + 并且可以将它映射到一个 JDBC 类型。比如:

    { ]]>

    - 使用上述的类型处理器将会覆盖已经存在的处理 Java 的 String 类型属性和 - VARCHAR 参数及结果的类型处理器。 + 使用上述的类型处理器将会覆盖已有的处理 Java String 类型的属性以及 + VARCHAR 类型的参数和结果的类型处理器。 要注意 MyBatis 不会通过窥探数据库元信息来决定使用哪种类型,所以你必须在参数和结果映射中指明那是 VARCHAR 类型的字段, 以使其能够绑定到正确的类型处理器上。这是因为 MyBatis 直到语句被执行时才清楚数据类型。

    @@ -1336,11 +1336,11 @@ public class ExampleTypeHandler extends BaseTypeHandler {
  • 在类型处理器的类上(TypeHandler class)增加一个 @MappedTypes 注解来指定与其关联的 Java 类型列表。 - 如果在 javaType 属性中也同时指定,则注解方式将被忽略。 + 如果在 javaType 属性中也同时指定,则注解上的配置将被忽略。
  • -

    可以通过两种方式来指定被关联的 JDBC 类型:

    +

    可以通过两种方式来指定关联的 JDBC 类型:

    • 在类型处理器的配置元素上增加一个 jdbcType @@ -1349,23 +1349,22 @@ public class ExampleTypeHandler extends BaseTypeHandler {
    • 在类型处理器的类上增加一个 @MappedJdbcTypes 注解来指定与其关联的 JDBC 类型列表。 - 如果在 jdbcType 属性中也同时指定,则注解方式将被忽略。 + 如果在 jdbcType 属性中也同时指定,则注解上的配置将被忽略。

    当在 ResultMap 中决定使用哪种类型处理器时,此时 Java 类型是已知的(从结果类型中获得),但是 JDBC 类型是未知的。 - 因此 Mybatis 使用 javaType=[Java 类型], jdbcType=null + 因此 Mybatis 使用 javaType=[Java 类型], jdbcType=null 的组合来选择一个类型处理器。 - 这意味着使用 @MappedJdbcTypes - 注解可以限制类型处理器的范围,同时除非显式的设置,否则类型处理器在 - ResultMap 中将是无效的。 - 如果希望在 ResultMap 中使用类型处理器,那么设置 + 这意味着使用 @MappedJdbcTypes + 注解可以限制类型处理器的作用范围,并且可以确保,除非显式地设置,否则类型处理器在 + ResultMap 中将不会生效。 + 如果希望能在 ResultMap 中隐式地使用类型处理器,那么设置 @MappedJdbcTypes 注解的 includeNullJdbcType=true 即可。 - 然而从 Mybatis 3.4.0 开始,如果只有一个注册的类型处理器来处理 Java - 类型,那么它将是 ResultMap 使用 Java - 类型时的默认值(即使没有 includeNullJdbcType=true)。 + 然而从 Mybatis 3.4.0 开始,如果某个 Java 类型只有一个注册的类型处理器,即使没有设置 includeNullJdbcType=true,那么这个类型处理器也会是 ResultMap 使用 Java + 类型时的默认处理器。

    最后,可以让 MyBatis 为你查找类型处理器:

    @@ -1376,9 +1375,9 @@ public class ExampleTypeHandler extends BaseTypeHandler { ]]>

    注意在使用自动发现功能的时候,只能通过注解方式来指定 JDBC 的类型。

    -

    你可以创建一个能够处理多个类的泛型类型处理器。为了使用泛型类型处理器, - 需要增加一个接受该类的 class 作为参数的构造器,这样在构造一个类型处理器的时候 - MyBatis 就会传入一个具体的类。

    +

    你可以创建能够处理多个类的泛型类型处理器。为了使用泛型类型处理器, + 需要增加一个接受该类的 class 作为参数的构造器,这样 MyBatis + 会在构造一个类型处理器实例的时候传入一个具体的类。

    extends BaseTypeHandler { @@ -1399,7 +1398,7 @@ public class GenericTypeHandler extends BaseTypeHandler {

    若想映射枚举类型 Enum,则需要从 EnumTypeHandler - 或者 EnumOrdinalTypeHandler 中选一个来使用。

    + 或者 EnumOrdinalTypeHandler 中选择一个来使用。

    比如说我们想存储取近似值时用到的舍入模式。默认情况下,MyBatis 会利用 EnumTypeHandler 来把 Enum 值转换成对应的名字。

    @@ -1408,8 +1407,8 @@ public class GenericTypeHandler extends BaseTypeHandler { 在某种意义上来说是比较特别的,其他的处理器只针对某个特定的类,而它不同,它会处理任意继承了 Enum 的类。 -

    不过,我们可能不想存储名字,相反我们的 DBA 会坚持使用整形值代码。那也一样轻而易举: - 在配置文件中把 EnumOrdinalTypeHandler 加到 typeHandlers 中即可, +

    不过,我们可能不想存储名字,相反我们的 DBA 会坚持使用整形值代码。那也一样简单:在配置文件中把 + EnumOrdinalTypeHandler 加到 typeHandlers 中即可, 这样每个 RoundingMode 将通过他们的序数值来映射成对应的整形数值。

    @@ -1417,9 +1416,9 @@ public class GenericTypeHandler extends BaseTypeHandler { ]]> -

    但是怎样能将同样的 Enum 既映射成字符串又映射成整形呢?

    +

    但要是你想在一个地方将 Enum 映射成字符串,在另外一个地方映射成整形值呢?

    - 自动映射器(auto-mapper)会自动地选用 EnumOrdinalTypeHandler 来处理, + 自动映射器(auto-mapper)会自动地选用 EnumOrdinalTypeHandler 来处理枚举类型, 所以如果我们想用普通的 EnumTypeHandler,就必须要显式地为那些 SQL 语句设置要使用的类型处理器。

    (下一节才开始介绍映射器文件,如果你是首次阅读该文档,你可能需要先跳过这里,过会再来看。)

    @@ -1461,13 +1460,13 @@ public class GenericTypeHandler extends BaseTypeHandler { ]]> -

    注意,这里的 select 语句强制使用 resultMap 来代替 resultType

    +

    注意,这里的 select 语句必须指定 resultMap 而不是 resultType

    -

    MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。 - 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。 - 如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。比如:

    +

    每次 MyBatis 创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。 + 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 + 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现。比如:

    ]]> -

    ObjectFactory 接口很简单,它包含两个创建用的方法,一个是处理默认构造方法的,另外一个是处理带参数的构造方法的。 - 最后,setProperties 方法可以被用来配置 ObjectFactory,在初始化你的 ObjectFactory 实例后, +

    ObjectFactory 接口很简单,它包含两个创建实例用的方法,一个是处理默认无参构造方法的,另外一个是处理带参数的构造方法的。 + 另外,setProperties 方法可以被用来配置 ObjectFactory,在初始化你的 ObjectFactory 实例后, objectFactory 元素体中定义的属性会被传递给 setProperties 方法。

    - MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括: + MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

    • @@ -1519,8 +1518,8 @@ public class ExampleObjectFactory extends DefaultObjectFactory {

    这些类中方法的细节可以通过查看每个方法的签名来发现,或者直接查看 MyBatis 发行包中的源代码。 如果你想做的不仅仅是监控方法的调用,那么你最好相当了解要重写的方法的行为。 - 因为如果在试图修改或重写已有方法的行为的时候,你很可能在破坏 MyBatis 的核心模块。 - 这些都是更低层的类和方法,所以使用插件的时候要特别当心。

    + 因为在试图修改或重写已有方法的行为时,很可能会破坏 MyBatis 的核心模块。 + 这些都是更底层的类和方法,所以使用插件的时候要特别当心。

    通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可。

    ]]>

    上面的插件将会拦截在 Executor 实例中所有的 “update” 方法调用, - 这里的 Executor 是负责执行低层映射语句的内部对象。

    + 这里的 Executor 是负责执行底层映射语句的内部对象。

    提示 覆盖配置类

    -

    除了用插件来修改 MyBatis 核心行为之外,还可以通过完全覆盖配置类来达到目的。只需继承后覆盖其中的每个方法,再把它传递到 SqlSessionFactoryBuilder.build(myConfig) 方法即可。再次重申,这可能会严重影响 MyBatis 的行为,务请慎之又慎。

    +

    除了用插件来修改 MyBatis 核心行为以外,还可以通过完全覆盖配置类来达到目的。只需继承后覆盖其中的某个方法,再把它传递到 SqlSessionFactoryBuilder.build(myConfig) 方法即可。再次重申,这可能会严重影响 MyBatis 的行为,务请慎之又慎。

    @@ -1580,13 +1579,13 @@ public class ExamplePlugin implements Interceptor { -

    如果忽略了环境参数,那么默认环境将会被加载,如下所示: +

    如果忽略了环境参数,那么将会加载默认环境,如下所示:

    -

    环境元素定义了如何配置环境。 +

    environments 元素定义了如何配置环境。

    @@ -1603,7 +1602,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert ]]>

    - 注意这里的关键点: + 注意一些关键点:

    • @@ -1620,20 +1619,20 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert

    - 默认的环境和环境 ID 是自解释的,因此一目了然。 - 你可以对环境随意命名,但一定要保证默认的环境 ID 要匹配其中一个环境 ID。 + 默认环境和环境 ID 顾名思义,一目了然。 + 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。

    事务管理器(transactionManager)

    -

    在 MyBatis 中有两种类型的事务管理器(也就是 type=”[JDBC|MANAGED]”):

    +

    在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):

    • - JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。 + JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
    • - MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 - 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。例如: + MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 + 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。例如: ]]> @@ -1644,8 +1643,8 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert 因为 Spring 模块会使用自带的管理器来覆盖前面的配置。

      - 这两种事务管理器类型都不需要设置任何属性。它们其实是类型别名,换句话说,你可以使用 - TransactionFactory 接口的实现类的完全限定名或类型别名代替它们。 + 这两种事务管理器类型都不需要设置任何属性。它们其实是类型别名,换句话说,你可以用 + TransactionFactory 接口实现类的全限定名或类型别名代替它们。

      dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

        -
      • 许多 MyBatis 的应用程序会按示例中的例子来配置数据源。虽然这是可选的,但为了使用延迟加载,数据源是必须配置的。 +
      • 大多数 MyBatis + 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但为了使用延迟加载,必须配置数据源。
      -

      有三种内建的数据源类型(也就是 type=”[UNPOOLED|POOLED|JNDI]”):

      +

      有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):

      - UNPOOLED– 这个数据源的实现只是每次被请求时打开和关闭连接。虽然有点慢,但对于在数据库连接可用性方面没有太高要求的简单应用程序来说,是一个很好的选择。 + UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对于对数据库连接可用性没有太高要求的简单应用程序来说,是一个很好的选择。 不同的数据库在性能方面的表现也是不一样的,对于某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。UNPOOLED 类型的数据源具有以下属性。:

        -
      • driver – 这是 JDBC 驱动的 Java 类的完全限定名(并不是 JDBC 驱动中可能包含的数据源类)。 +
      • driver – 这是 JDBC 驱动的 Java 类全限定名(并不是 JDBC 驱动中可能包含的数据源类)。
      • url – 这是数据库的 JDBC URL 地址。
      • @@ -1695,19 +1695,18 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert
        • driver.encoding=UTF8
        -

        这将通过 DriverManager.getConnection(url,driverProperties) 方法传递值为 +

        这将通过 DriverManager.getConnection(url, driverProperties) 方法传递值为 UTF8encoding 属性给数据库驱动。

        POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 - 这是一种使得并发 Web 应用快速响应请求的流行处理方式。 + 这种处理方式很流行,能使并发 Web 应用快速响应请求。

        除了上述提到 UNPOOLED 下的属性外,还有更多属性用来配置 POOLED 的数据源:

          -
        • poolMaximumActiveConnections – 在任意时间可以存在的活动(也就是正在使用)连接数量,默认值:10 +
        • poolMaximumActiveConnections – 在任意时间可存在的活动(正在使用)连接数量,默认值:10
        • poolMaximumIdleConnections – 任意时间可能存在的空闲连接数。 -
        • poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)
        • @@ -1716,9 +1715,9 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert
        • poolMaximumLocalBadConnectionTolerance – 这是一个关于坏连接容忍度的底层设置, 作用于每一个尝试从缓存池获取连接的线程。 如果这个线程获取到的是一个坏的连接,那么这个数据源允许这个线程尝试重新获取一个新的连接,但是这个重新尝试的次数不应该超过 poolMaximumIdleConnections - 与 poolMaximumLocalBadConnectionTolerance 之和。 默认值:3 (新增于 3.4.5) + 与 poolMaximumLocalBadConnectionTolerance 之和。 默认值:3(新增于 3.4.5)
        • -
        • poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动失败时带有一个恰当的错误消息。 +
        • poolPingQuery – 发送到数据库的侦测查询,用来检验连接是否正常工作并准备接受请求。默认是“NO PING QUERY SET”,这会导致多数数据库驱动出错时返回恰当的错误消息。
        • poolPingEnabled – 是否启用侦测查询。若开启,需要设置 poolPingQuery 属性为一个可执行的 SQL 语句(最好是一个速度非常快的 SQL 语句),默认值:false。
        • @@ -1726,20 +1725,20 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert

        - JNDI – 这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。这种数据源配置只需要两个属性: + JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。这种数据源配置只需要两个属性:

        • initial_context – 这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么将会直接从 InitialContext 中寻找 data_source 属性。
        • -
        • data_source – 这是引用数据源实例位置的上下文的路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。 +
        • data_source – 这是引用数据源实例位置的上下文路径。提供了 initial_context 配置时会在其返回的上下文中进行查找,没有提供时则直接在 InitialContext 中查找。
        -

        和其他数据源配置类似,可以通过添加前缀“env.”直接把属性传递给初始上下文。比如: +

        和其他数据源配置类似,可以通过添加前缀“env.”直接把属性传递给 InitialContext。比如:

        • env.encoding=UTF8
        -

        这就会在初始上下文(InitialContext)实例化时往它的构造方法传递值为 UTF8encoding 属性。 +

        这就会在 InitialContext 实例化时往它的构造方法传递值为 UTF8encoding 属性。

        @@ -1765,7 +1764,7 @@ public class C3P0DataSourceFactory extends UnpooledDataSourceFactory { } }]]> -

        为了令其工作,记得为每个希望 MyBatis 调用的 setter 方法在配置文件中增加对应的属性。 +

        为了令其工作,记得在配置文件中为每个希望 MyBatis 调用的 setter 方法增加对应的属性。 下面是一个可以连接至 PostgreSQL 数据库的例子:

        @@ -1781,17 +1780,17 @@ public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {

        MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 - MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。 + MyBatis 会加载带有匹配当前数据库 databaseId 属性和不带 databaseId 属性的所有语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。 - 为支持多厂商特性只要像下面这样在 mybatis-config.xml 文件中加入 databaseIdProvider 即可: + 为支持多厂商特性,只要像下面这样在 mybatis-config.xml 文件中加入 databaseIdProvider 即可:

        ]]>

        - DB_VENDOR 对应的 databaseIdProvider 实现会将 databaseId 设置为 + databaseIdProvider 对应的 DB_VENDOR 实现会将 databaseId 设置为 DatabaseMetaData#getDatabaseProductName() 返回的字符串。 - 由于通常情况下这些字符串都非常长而且相同产品的不同版本会返回不同的值,所以你可能想通过设置属性别名来使其变短,如下: + 由于通常情况下这些字符串都非常长,而且相同产品的不同版本会返回不同的值,你可能想通过设置属性别名来使其变短:

        @@ -1801,8 +1800,8 @@ public class C3P0DataSourceFactory extends UnpooledDataSourceFactory { ]]>

        - 在提供了属性别名时,DB_VENDOR 的 databaseIdProvider 实现会将 databaseId - 设置为第一个数据库产品名与属性中的名称相匹配的值,如果没有匹配的属性将会设置为 “null”。 + 在提供了属性别名时,databaseIdProvider 的 DB_VENDOR 实现会将 databaseId + 设置为数据库产品名与属性中的名称第一个相匹配的值,如果没有匹配的属性,将会设置为 “null”。 在这个例子中,如果 getDatabaseProductName() 返回“Oracle (DataDirect)”,databaseId 将被设置为“oracle”。

        @@ -1823,11 +1822,11 @@ public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {

        - 既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了。 - 但是首先我们需要告诉 MyBatis 到哪里去找到这些语句。 - Java 在自动查找这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。 - 你可以使用相对于类路径的资源引用, - 或完全限定资源定位符(包括 file:/// 的 URL),或类名和包名等。例如: + 既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 + 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 + 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 + MyBatis 到哪里去找映射文件。 + 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 的 URL),或类名和包名等。例如:

        diff --git a/src/site/zh/xdoc/getting-started.xml b/src/site/zh/xdoc/getting-started.xml index bb71a127d59..488faf33046 100644 --- a/src/site/zh/xdoc/getting-started.xml +++ b/src/site/zh/xdoc/getting-started.xml @@ -32,8 +32,8 @@

        要使用 MyBatis, 只需将 mybatis-x.x.x.jar - 文件置于 classpath 中即可。

        -

        如果使用 Maven 来构建项目,则需将下面的 dependency 代码置于 pom.xml 文件中:

        + 文件置于类路径(classpath)中即可。

        +

        如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中:

        org.mybatis @@ -53,9 +53,9 @@

        从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。 - 但是也可以使用任意的输入流(InputStream)实例,包括字符串形式的文件路径或者 - file:// 的 URL 形式的文件路径来配置。MyBatis 包含一个名叫 Resources - 的工具类,它包含一些实用方法,可使从 classpath 或其他位置加载资源文件更加容易。 + 但是也可以使用任意的输入流(InputStream)实例,比如从字符串形式的文件路径或者 + file:// 的 URL 形式的文件路径中构造而来的输入流。MyBatis 包含一个名叫 Resources + 的工具类,它包含一些实用方法,能让从类路径或其它位置加载资源文件更加容易。

        ]]>

        - 当然,还有很多可以在 XML 文件中进行配置,上面的示例指出的则是最关键的部分。 + 当然,还有很多设置可以在 XML 文件中进行配置,上面的示例罗列的是最关键的部分。 要注意 XML 头部的声明,它用来验证 XML 文档正确性。environment 元素体中包含了事务管理和连接池的配置。mappers 元素则是包含一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。 @@ -112,7 +112,7 @@ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(confi

        注意该例中,configuration 添加了一个映射器类(mapper class)。映射器类是 - Java 类,它们包含 SQL 映射语句的注解从而避免依赖 XML 文件。不过,由于 + Java 类,它们包含 SQL 映射注解从而避免依赖 XML 文件。不过,由于 Java 注解的一些限制以及某些 MyBatis 映射的复杂性,要使用大多数高级映射(比如:嵌套联合映射),仍然需要使用 XML 配置。有鉴于此,如果存在一个同名 XML 配置文件,MyBatis 会自动查找并加载它(在这个例子中,基于类路径和 BlogMapper.class 的类名,会加载 @@ -133,8 +133,8 @@ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(confi

        诚然,这种方式能够正常工作,并且对于使用旧版本 MyBatis 的用户来说也比较熟悉。不过现在有了一种更简洁的方式 - ——使用正确描述每个语句的参数和返回值的接口(比如 - BlogMapper.class),你现在不仅可以执行更清晰和类型安全的代码,而且还不用担心易错的字符串字面值以及强制类型转换。

        + ——使用正确匹配每个语句的参数和返回值的接口(比如 + BlogMapper.class),现在你不仅可以执行更清晰和类型更安全的代码,而且还不用担心可能出错的字符串字面值以及强制类型转换。

        例如:

        @@ -153,7 +153,7 @@ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(confi

        在上面提到的例子中,一个语句既可以通过 XML 定义,也可以通过注解定义。我们先看看 - XML 定义语句的方式,事实上 MyBatis 提供的全部特性都可以利用基于 XML 的映射语言来实现,这使得 + XML 定义语句的方式,事实上 MyBatis 提供的所有特性都可以利用基于 XML 的映射语言来实现,这使得 MyBatis 在过去的数年间得以流行。如果你以前用过 MyBatis,你应该对这个概念比较熟悉。 不过自那以后,XML 的配置也改进了许多,我们稍后还会再提到。这里给出一个基于 XML 映射语句的示例,它应该可以满足上述示例中 SqlSession 的调用。 @@ -170,31 +170,28 @@ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(confi ]]>

        - 为了这个简单的例子,我们似乎写了不少配置,但实际上它并不多。在一个 + 为了这个简单的例子,我们似乎写了不少配置,但实际上并不多。在一个 XML 映射文件中,可以定义无数个映射语句,这样一来,XML 头部和文档类型声明占去的部分就显得微不足道了。而文件的剩余部分具备自解释性,很容易理解。 在命名空间 “org.mybatis.example.BlogMapper” 中定义了一个名为 “selectBlog” - 的映射语句,允许你使用指定的完全限定名 + 的映射语句,允许你使用全限定名 “org.mybatis.example.BlogMapper.selectBlog” 来调用映射语句,就像上面例子中那样:

        - 你可能注意到这和使用完全限定名调用 Java - 对象的方法类似。这样,该命名就可以直接映射到在命名空间中同名的 - Mapper 类,并将已映射的 select 语句中的名字、参数和返回类型匹配成方法。 - 因此你就可以像上面那样很容易地调用这个对应 Mapper - 接口的方法,就像下面这样: + 你可能会注意到这和使用全限定名调用 Java + 对象的方法类似。这样,该命名就可以直接映射到在命名空间中同名的映射器类,并将已映射的 + select 语句匹配到对应名字、参数和返回类型的方法。因此你就可以像上面那样很容易地调用这个对应映射器接口的方法,就像下面这样:

        - 第二种方法有很多优势,首先它不依赖于字符串字面值,会更安全一点; - 其次,如果你的 IDE 有代码补全功能,那么代码补全可以帮你快速选择已映射的 SQL - 语句。 + 第二种方法有很多优势,首先它不依赖于字符串字面值,会更安全一点;其次,如果你的 + IDE 有代码补全功能,那么代码补全可以帮你快速选择已映射的 SQL 语句。


        @@ -206,7 +203,7 @@ Blog blog = mapper.selectBlog(101);]]> 但现在,随着命名空间越发重要,你必须指定命名空间。

        - 命名空间的作用有两个,一个是利用更长的完全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。就算你觉得暂时用不到接口绑定,你也应该遵循这里的规定,以防哪天你改变了主意。 + 命名空间的作用有两个,一个是利用更长的全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。就算你觉得暂时用不到接口绑定,你也应该遵循这里的规定,以防哪天你改变了主意。 长远来看,只要将命名空间置于合适的 Java 包命名空间之中,你的代码会变得更加整洁,也有利于你更方便地使用 MyBatis。

        @@ -270,7 +267,7 @@ public interface BlogMapper {

        SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 - SqlSessionFactory 被视为一种代码“坏味道(bad smell)”。因此 + SqlSessionFactory 被视为一种代码“坏味道”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

        @@ -282,7 +279,7 @@ public interface BlogMapper { 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,要考虑 SqlSession 放在一个和 HTTP 请求对象相似的作用域中。 换句话说,每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它。 - 这个关闭操作是很重要的,你应该把这个关闭操作放到 finally 块中以确保每次都能执行关闭。 + 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:

        映射器实例

        - 映射器是一些由你创建的、绑定你映射的语句的接口。映射器接口的实例是从 - SqlSession 中获得的。因此从技术层面讲,任何映射器实例的最大作用域是和请求它们的 - SqlSession 相同的。尽管如此,映射器实例的最佳作用域是方法作用域。 - 也就是说,映射器实例应该在调用它们的方法中被请求,用过之后即可丢弃。 - 并不需要显式地关闭映射器实例,尽管在整个请求作用域保持映射器实例也不会有什么问题,但是你很快会发现,像 - SqlSession 一样,在这个作用域上管理太多的资源的话会难于控制。 + 映射器是一些由你创建的绑定映射语句的接口。映射器接口的实例是从 + SqlSession 中获得的。因此从技术层面讲,任何映射器实例的最大作用域与请求它们的 + SqlSession 相同。尽管如此,映射器实例的最佳作用域是方法作用域。 + 也就是说,映射器实例应该在调用它们的方法中被请求,使用完毕之后即可丢弃。 + 映射器实例并不需要被显式地关闭。尽管在整个请求作用域保留映射器实例不会有什么问题,但是你很快会发现,像 + SqlSession 一样,在这个作用域上管理太多的资源会难以控制。 为了避免这种复杂性,最好把映射器放在方法作用域内。下面的示例就展示了这个实践:

        -

        MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis - 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis - 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old +

        MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis + 免除了几乎所有的 JDBC 代码以及参数设置和结果集获取的工作。MyBatis + 可以通过简单的 XML 或注解来配置和映射原生类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

        -

        如果你发现文档有任何的缺失,或者缺少某一个功能点的说明,最好的解决办法是先自己学习,并且为缺失的部份补上相应的文档。

        +

        如果你发现文档有任何遗漏,或者缺少某一个功能点的说明,最好的解决办法是先自己学习,然后为遗漏的部份补上相应的文档。

        该文档 xdoc 格式的源码文件可通过项目的 - Git 代码库来获取。Fork 该源码库,作出更新,并提交 Pull Request 吧。

        + Git 代码库来获取。复刻该源码库,作出更新,并提交 Pull Request 吧。

        还有其他像你一样的人都需要阅读这份文档,而你,就是这份文档最好的作者。

        diff --git a/src/site/zh/xdoc/sqlmap-xml.xml b/src/site/zh/xdoc/sqlmap-xml.xml index 097b3570b72..079c0848ea6 100644 --- a/src/site/zh/xdoc/sqlmap-xml.xml +++ b/src/site/zh/xdoc/sqlmap-xml.xml @@ -20,40 +20,40 @@ xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"> - MyBatis 3 | XML 映射文件 + MyBatis 3 | XML 映射器 Clinton Begin Nan Lei Dongxu Wang -
        -

        MyBatis 的真正强大在于它的映射语句,这是它的魔力所在。由于它的异常强大,映射器的 +

        +

        MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 - 95% 的代码。MyBatis 为聚焦于 SQL 而构建,以尽可能地为你减少麻烦。

        + 95% 的代码。MyBatis 以 SQL 为关注核心,尽可能地为你扫除障碍。

        SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):

        • cache - – 对给定命名空间的缓存配置。 + – 该命名空间的缓存配置。
        • cache-ref - – 对其他命名空间缓存配置的引用。 + – 引用其它命名空间的缓存配置。
        • resultMap - – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。 + – 最复杂也是最强大的元素,用来描述如何从数据库结果集中加载对象。
        • parameterMap - – 已被废弃!老式风格的参数映射。更好的办法是使用内联参数,此元素可能在将来被移除。文档中不会介绍此元素。 + – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
        • sql - – 可被其他语句引用的可重用语句块。 + – 可被其它语句引用的可重用语句块。
        • insert @@ -75,7 +75,8 @@

          下一部分将从语句本身开始来描述每个元素的细节。

          -

          查询语句是 MyBatis 中最常用的元素之一,光能把数据存到数据库中价值并不大,只有还能重新取出来才有用,多数应用也都是查询比修改要频繁。对每个插入、更新或删除操作,通常间隔多个查询操作。这是 MyBatis 的基本原则之一,也是将焦点和努力放在查询和结果映射的原因。简单查询的 select 元素是非常简单的。比如: +

          查询语句是 MyBatis 中最常用的元素之一——光能把数据存到数据库中价值并不大,只有能重新取出来才有用,多数应用也都是查询比修改要频繁。 + 对每个插入、更新或删除操作,通常间隔多个查询操作。这是 MyBatis 的基本原则之一,也是将焦点和努力放在查询和结果映射的原因。一个简单查询的 select 元素是非常简单的。比如:

          @@ -83,7 +84,7 @@ ]]>

          - 这个语句被称作 selectPerson,接受一个 int(或 Integer)类型的参数,并返回一个 + 这个语句名为 selectPerson,接受一个 int(或 Integer)类型的参数,并返回一个 HashMap 类型的对象,其中的键是列名,值便是结果行中的对应值。

          @@ -103,7 +104,7 @@ ps.setInt(1,id);]]>

          当然,使用 JDBC 意味着需要更多的代码来提取结果并将它们映射到对象实例中,而这就是 - MyBatis 节省你时间的地方。参数和结果映射还有更深入的细节。这些细节会分别在后面单独的小节中呈现。 + MyBatis 为你节省时间的地方。参数和结果映射还有更深入的细节。这些细节会分别在后面单独的小节中呈现。

          @@ -141,8 +142,8 @@ ps.setInt(1,id);]]> parameterType - 将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 - MyBatis 可以通过类型处理器(TypeHandler) 推断出具体传入语句的参数,默认值为未设置(unset)。 + 将会传入这条语句的参数类的全限定名或别名。这个属性是可选的,因为 + MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 @@ -151,23 +152,23 @@ ps.setInt(1,id);]]> - 这是引用外部 parameterMap 的已经被废弃的方法。请使用内联参数映射和 parameterType 属性。 + 这是引用外部 parameterMap 已被废弃的方法。请使用行内参数映射和 parameterType 属性。 resultType - 从这条语句中返回的期望类型的类的完全限定名或别名。 - 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。可以使用 + 期望从这条语句中返回的类型全限定名或别名。 + 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。可以使用 resultType 或 resultMap,但不能同时使用。 resultMap - 外部 resultMap 的命名引用。结果集的映射是 MyBatis - 最强大的特性,如果你对其理解透彻,许多复杂映射的情形都能迎刃而解。可以使用 + 对外部 resultMap 的命名引用。结果映射是 MyBatis + 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。可以使用 resultMap 或 resultType,但不能同时使用。 @@ -192,14 +193,14 @@ ps.setInt(1,id);]]> fetchSize - 这是一个给驱动的提示,尝试让驱动程序每次批量返回的结果行数和这个设置值相等。 + 这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。 默认值为未设置(unset)(依赖驱动)。 statementType - STATEMENT,PREPARED 或 CALLABLE 中的一个。这会让 MyBatis 分别使用 + 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 @@ -220,15 +221,15 @@ ps.setInt(1,id);]]> resultOrdered - 这个设置仅针对嵌套结果 select 语句适用:如果为 - true,就是假设包含了嵌套结果集或是分组,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。 - 这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false。 + 这个设置仅针对嵌套结果 select 语句:如果为 + true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用。 + 这就使得在获取嵌套结果集的时候不至于内存不够用。默认值:falseresultSets - 这个设置仅对多结果集的情况适用。它将列出语句执行后返回的结果集并给每个结果集一个名称,名称是逗号分隔的。 + 这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,名称是逗号分隔的。 @@ -275,13 +276,13 @@ ps.setInt(1,id);]]> id - 命名空间中的唯一标识符,可被用来代表这条语句。 + 在命名空间中唯一的标识符,可以被用来引用这条语句。 parameterType - 将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为 MyBatis - 可以通过类型处理器推断出具体传入语句的参数,默认值为未设置(unset)。 + 将会传入这条语句的参数类的全限定名或别名。这个属性是可选的,因为 + MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 @@ -289,7 +290,7 @@ ps.setInt(1,id);]]> parameterMap - 这是引用外部 parameterMap 的已经被废弃的方法。请使用内联参数映射和 parameterType 属性。 + 这是引用外部 parameterMap 已被废弃的方法。请使用行内参数映射和 parameterType 属性。 @@ -306,28 +307,28 @@ ps.setInt(1,id);]]> statementType - STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 + 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。 useGeneratedKeys - (仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 + (仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。 keyProperty - (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 - getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认值:未设置(unset)。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 + (仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会通过 + getGeneratedKeys 的返回值或通过 insert 语句的 selectKey 子元素设置它的键值,默认值:未设置(unset)。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 keyColumn - (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望使用多个生成的列,也可以设置为逗号分隔的属性名称列表。 + (仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果希望使用多个生成的列,也可以设置为逗号分隔的属性名称列表。 @@ -340,7 +341,7 @@ ps.setInt(1,id);]]> -

          下面就是 insert,update 和 delete 语句的示例:

          +

          下面是 insert,update 和 delete 语句的示例:

          insert into Author (id,username,password,email,bio) @@ -360,9 +361,9 @@ ps.setInt(1,id);]]> delete from Author where id = #{id} ]]> -

          如前所述,插入语句的配置规则更加丰富,在插入语句里面有一些额外的属性和子元素用来处理主键的生成,而且有多种生成方式。

          +

          如前所述,插入语句的配置规则更加丰富,在插入语句里面有一些额外的属性和子元素用来处理主键的生成,并且提供了多种生成方式。

          -

          首先,如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上就 OK 了。例如,如果上面的 Author 表已经对 id 使用了自动生成的列类型,那么语句可以修改为:

          +

          首先,如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置为目标属性就 OK 了。例如,如果上面的 Author 表已经在 id 列上使用了自动生成,那么语句可以修改为:

          @@ -383,12 +384,12 @@ ps.setInt(1,id);]]> ]]>

          - 对于不支持自动生成类型的数据库或可能不支持自动生成主键的 JDBC 驱动,MyBatis 有另外一种方法来生成主键。 + 对于不支持自动生成主键列的数据库和可能不支持自动生成主键的 JDBC 驱动,MyBatis 有另外一种方法来生成主键。

          - 这里有一个简单(甚至很傻)的示例,它可以生成一个随机 ID(你最好不要这么做,但这里展示了 - MyBatis 处理问题的灵活性及其所关心的广度): + 这里有一个简单(甚至很傻)的示例,它可以生成一个随机 ID(最好不要这么做,这里只是为了展示 + MyBatis 处理问题的灵活性和宽容度):

          @@ -400,8 +401,8 @@ ps.setInt(1,id);]]> values (#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR}) ]]> -

          在上面的示例中,selectKey 元素中的语句将会首先运行,Author 的 id - 会被设置,然后插入语句会被调用。这可以提供给你一个与数据库中自动生成主键类似的行为,同时保持了 Java 代码的简洁。 +

          在上面的示例中,selectKey 元素中的语句将会首先运行,并设置 Author 的 + id,然后插入语句会被调用。这样就提供了与数据库中自动生成主键类似的行为,同时保持了 Java 代码的简洁。

          selectKey 元素描述如下:

          @@ -423,7 +424,7 @@ ps.setInt(1,id);]]> keyProperty - selectKey 语句结果应该被设置的目标属性。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 + selectKey 语句结果应该被设置到的目标属性。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。 @@ -435,23 +436,26 @@ ps.setInt(1,id);]]> resultType - 结果的类型。MyBatis 通常可以推断出来,但是为了更加精确,写上也不会有什么问题。MyBatis 允许将任何简单类型用作主键的类型,包括字符串。如果希望作用于多个生成的列,则可以使用一个包含期望属性的 Object 或一个 Map。 + 结果的类型。通常 MyBatis 可以推断出来,但是为了更加精确,写上也不会有什么问题。MyBatis + 允许将任何简单类型用作主键的类型,包括字符串。如果希望作用于多个生成的列,则可以使用包含期望属性的 + Object 或 Map。 order - 这可以被设置为 BEFORE 或 AFTER。如果设置为 - BEFORE,那么它会首先生成主键,设置 keyProperty 然后执行插入语句。如果设置为 - AFTER,那么先执行插入语句,然后是 selectKey 中的语句 - 这和 Oracle + 可以设置为 BEFOREAFTER。如果设置为 + BEFORE,那么它首先会生成主键,设置 keyProperty 再执行插入语句。如果设置为 + AFTER,那么先执行插入语句,然后是 selectKey 中的语句 - 这和 Oracle 数据库的行为相似,在插入语句内部可能有嵌入索引调用。 statementType - 与前面相同,MyBatis 支持 STATEMENT,PREPARED 和 CALLABLE - 语句的映射类型,分别代表 PreparedStatement 和 CallableStatement 类型。 + 与前面相同,MyBatis 支持 STATEMENTPREPAREDCALLABLE + 类型的映射语句,分别代表 Statement, PreparedStatement 和 + CallableStatement 类型。 diff --git a/src/site/zh/xdoc/statement-builders.xml b/src/site/zh/xdoc/statement-builders.xml index a31a2354cba..74b7824cab1 100644 --- a/src/site/zh/xdoc/statement-builders.xml +++ b/src/site/zh/xdoc/statement-builders.xml @@ -20,7 +20,7 @@ xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"> - MyBatis 3 | SQL语句构建器 + MyBatis 3 | SQL 语句构建器 Clinton Begin Nan Lei @@ -72,7 +72,7 @@ private String selectPersonSql() { } ]]> -

          这个例子有什么特别的地方吗?仔细看一下你会发现,你不用担心可能会重复出现的 "AND" 关键字,或者要做出拼接 "WHERE" 还是 "AND" 还是不拼接的选择。SQL 类已经为你处理了哪里应该插入 "WHERE"、哪里应该使用 "AND" 的问题,并帮你完成所有的字符串拼接工作。 +

          这个例子有什么特别的地方吗?仔细看一下你会发现,你不用担心可能会重复出现的 "AND" 关键字,或者要做出用 "WHERE" 还是 "AND" 还是不用拼接的选择。SQL 类已经为你处理了哪里应该插入 "WHERE"、哪里应该使用 "AND" 的问题,并帮你完成所有的字符串拼接工作。

          @@ -520,7 +520,7 @@ public String selectPersonsWithFetchFirstSql() {

          - 在版本 3.2 之前,我们采取了不太一样的措施,通过使用 ThreadLocal 变量来掩盖一些对 Java DSL 不太友好的语言限制。这种方式已被废弃,在这个领域中,人们已经对现代框架使用的构建器类型和匿名内部类习以为常。因此,SelectBuilder 和 SqlBuilder 类都被废弃了。 + 在版本 3.2 之前,我们采取了不太一样的措施,通过使用 ThreadLocal 变量来掩盖一些对 Java DSL 不太友好的语言限制。这种方式已被废弃,在这个领域,人们已经对现代框架使用的构建器模式和匿名内部类模式习以为常了。因此,SelectBuilder 和 SqlBuilder 类都被废弃了。

          下面的方法仅仅适用于废弃的 SqlBuilder 和 SelectBuilder 类。 From 68f161944a37a76ad40f92ec46e0ef8bb75bc58e Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 31 Mar 2019 01:15:12 +0800 Subject: [PATCH 6/9] Polish documents --- src/site/zh/xdoc/configuration.xml | 133 ++++++++++++++------------- src/site/zh/xdoc/getting-started.xml | 114 +++++++++++------------ src/site/zh/xdoc/index.xml | 8 +- src/site/zh/xdoc/sqlmap-xml.xml | 89 +++++++++--------- 4 files changed, 173 insertions(+), 171 deletions(-) diff --git a/src/site/zh/xdoc/configuration.xml b/src/site/zh/xdoc/configuration.xml index 8f51b45e9a0..d560a7d0be8 100644 --- a/src/site/zh/xdoc/configuration.xml +++ b/src/site/zh/xdoc/configuration.xml @@ -58,12 +58,12 @@

        -

        这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。例如:

        +

        这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。例如:

        ]]> -

        然后其中的属性就可以在整个配置文件中被用来替换需要动态配置的属性值。比如: +

        设置好的属性可以在整个配置文件中用来替换需要动态配置的属性值。比如:

        @@ -73,21 +73,21 @@ ]]>

        这个例子中的 username 和 password 将会由 properties 元素中设置的相应值来替换。 driver 和 url 属性将会由 config.properties 文件中对应的值来替换。这样就为配置提供了诸多灵活选择。

        -

        也可以在 SqlSessionFactoryBuilder.build() 方法中传入属性。例如:

        +

        也可以在 SqlSessionFactoryBuilder.build() 方法中传入属性值。例如:

        -

        如果属性在不只一个地方进行了配置,那么 MyBatis 将按照下面的顺序来加载:

        +

        如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:

        • 首先读取在 properties 元素体内指定的属性。
        • -
        • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件或根据 - url 属性指定的路径读取属性文件,并覆盖已读取的同名属性。 +
        • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 + url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
        • -
        • 最后读取作为方法参数传递的属性,并覆盖已读取的同名属性。 +
        • 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。

        因此,通过方法参数传递的属性具有最高优先级,resource/url @@ -103,8 +103,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ ]]>

        - 这个特性默认是关闭的。如果你想为占位符指定一个默认值, - 你应该添加一个特定的属性来开启这个特性。例如: + 这个特性默认是关闭的。要启用这个特性,需要添加一个特定的属性来开启这个特性。例如:

        ]]>

        - 提示 如果你已经使用 ":" - 作为属性的键(如:db:username) ,或者你已经在 SQL - 定义中使用 OGNL 表达式的三元运算符(如: ${tableName != null ? - tableName : 'global_constants'}),你应该通过设置特定的属性来修改分隔键名和默认值的字符。例如: + 提示 + 如果你在属性名中使用了 ":" + 字符(如:db:username),或者在 SQL + 映射中使用了 OGNL 表达式的三元运算符(如: ${tableName != null ? + tableName : 'global_constants'}),就需要设置特定的属性来修改分隔属性名和默认值的字符。例如:

        - 当开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 + 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods)。 true | false - false (在 3.4.1 及之前的版本默认值为 true) + false (在 3.4.1 及之前的版本中默认为 true) @@ -196,7 +196,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ multipleResultSetsEnabled - 是否允许单个语句返回多结果集(需要驱动支持)。 + 是否允许单个语句返回多结果集(需要数据库驱动支持)。 true | false @@ -210,7 +210,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ useColumnLabel - 使用列标签代替列名。不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测试这两种不同的模式来观察使用驱动的结果。 + 使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。 true | false @@ -224,8 +224,8 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ useGeneratedKeys - 允许 JDBC 支持自动生成主键,需要驱动支持。如果设置为 - true,将强制使用自动生成主键。尽管一些驱动不支持此特性,但仍可正常工作(如 Derby)。 + 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 + true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 true | false @@ -240,8 +240,8 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ 指定 MyBatis 应如何自动映射列到字段或属性。 - NONE 表示取消自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 - FULL 会自动映射任意复杂的结果集(无论是否嵌套)。 + NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 + FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 NONE, PARTIAL, FULL @@ -255,12 +255,12 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ autoMappingUnknownColumnBehavior - 指定发现自动映射目标未知列(或者未知属性类型)的行为。 + 指定发现自动映射目标未知列(或未知属性类型)的行为。
        • NONE: 不做任何反应
        • WARNING: - 输出提醒日志 ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' - 的日志等级必须设置为 WARN)
        • + 输出警告日志('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' + 的日志等级必须设置为 WARN
        • FAILING: 映射失败 (抛出 SqlSessionException)
        @@ -277,7 +277,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); - BATCH 执行器将重用语句并执行批量更新。 + BATCH 执行器不仅重用语句还会执行批量更新。 SIMPLE @@ -293,7 +293,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ defaultStatementTimeout - 设置超时时间,它决定驱动等待数据库响应的秒数。 + 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 任意正整数 @@ -395,10 +395,10 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ 当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 - 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 + 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 - JdbcType 常量,常用值:NULL, VARCHAR 或 OTHER。 + JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。 OTHER @@ -426,7 +426,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ 指定动态 SQL 生成使用的默认脚本语言。 - 一个类型别名或完全限定类名。 + 一个类型别名或全限定类名。 org.apache.ibatis.scripting.xmltags.XMLLanguageDriver @@ -440,7 +440,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ 指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5) - 一个类型别名或完全限定类名。 + 一个类型别名或全限定类名。 org.apache.ibatis.type.EnumTypeHandler @@ -453,7 +453,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null - 值初始化的时候比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。 + 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。 true | false @@ -467,9 +467,9 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ returnInstanceForEmptyRow - 当返回行的所有列都是空时,MyBatis默认返回 null。 - 当开启这个设置时,MyBatis会返回一个空实例。 - 请注意,它也适用于嵌套的结果集 (如集合或关联)。(新增于 3.4.2) + 当返回行的所有列都是空时,MyBatis默认返回 null。 + 当开启这个设置时,MyBatis会返回一个空实例。 + 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2) true | false @@ -511,7 +511,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ proxyFactory - 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 + 指定 Mybatis 创建可延迟加载对象所用到的代理工具。 CGLIB | JAVASSIST @@ -540,7 +540,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ 允许使用方法签名中的名称作为语句参数名称。 - 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1) + 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1) true | false @@ -591,7 +591,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ

        类型别名可为 Java 类型设置一个缩写名字。 - 它只和 XML 配置有关,存在的意义仅在于减少全限定类名的冗余。例如:

        + 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:

        @@ -617,7 +617,7 @@ public class Author { ... } ]]> -

        这是一些为常见的 Java 类型内建的相应的类型别名。它们都是不区分大小写的,注意对基本类型名称重复采取的特殊命名风格。

        +

        下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

        @@ -850,7 +850,7 @@ public class Author {
        -

        MyBatis 在设置预处理语句(PreparedStatement)中的参数或在结果集中取出一个值时, +

        MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。

        提示 @@ -1132,7 +1132,7 @@ public class Author { Enumeration Type - VARCHAR 或任何兼容的字符串类型,用以存储枚举的名称(而不是索引值) + VARCHAR 或任何兼容的字符串类型,用来存储枚举的名称(而不是索引序数值) @@ -1144,7 +1144,7 @@ public class Author { 任何兼容的 NUMERICDOUBLE - 类型,存储枚举的序数值(而不是名称)。 + 类型,用来存储枚举的序数值(而不是名称)。 @@ -1285,7 +1285,7 @@ public class Author { 你可以重写已有的类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。 具体做法为:实现 org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, - 并且可以将它映射到一个 JDBC 类型。比如: + 并且可以(可选地)将它映射到一个 JDBC 类型。比如:

        {

        使用上述的类型处理器将会覆盖已有的处理 Java String 类型的属性以及 VARCHAR 类型的参数和结果的类型处理器。 - 要注意 MyBatis 不会通过窥探数据库元信息来决定使用哪种类型,所以你必须在参数和结果映射中指明那是 VARCHAR 类型的字段, + 要注意 MyBatis 不会通过检测数据库元信息来决定使用哪种类型,所以你必须在参数和结果映射中指明字段是 VARCHAR 类型, 以使其能够绑定到正确的类型处理器上。这是因为 MyBatis 直到语句被执行时才清楚数据类型。

        @@ -1334,8 +1334,8 @@ public class ExampleTypeHandler extends BaseTypeHandler { javaType 属性(比如:javaType="String");

      • - 在类型处理器的类上(TypeHandler class)增加一个 - @MappedTypes 注解来指定与其关联的 Java 类型列表。 + 在类型处理器的类上增加一个 + @MappedTypes 注解指定与其关联的 Java 类型列表。 如果在 javaType 属性中也同时指定,则注解上的配置将被忽略。
      @@ -1348,7 +1348,7 @@ public class ExampleTypeHandler extends BaseTypeHandler {
    • 在类型处理器的类上增加一个 @MappedJdbcTypes - 注解来指定与其关联的 JDBC 类型列表。 + 注解指定与其关联的 JDBC 类型列表。 如果在 jdbcType 属性中也同时指定,则注解上的配置将被忽略。
    @@ -1367,7 +1367,7 @@ public class ExampleTypeHandler extends BaseTypeHandler { 类型时的默认处理器。

    -

    最后,可以让 MyBatis 为你查找类型处理器:

    +

    最后,可以让 MyBatis 帮你查找类型处理器:

    @@ -1377,8 +1377,8 @@ public class ExampleTypeHandler extends BaseTypeHandler {

    注意在使用自动发现功能的时候,只能通过注解方式来指定 JDBC 的类型。

    你可以创建能够处理多个类的泛型类型处理器。为了使用泛型类型处理器, 需要增加一个接受该类的 class 作为参数的构造器,这样 MyBatis - 会在构造一个类型处理器实例的时候传入一个具体的类。

    + 会在构造一个类型处理器实例的时候传入一个具体的类。

    extends BaseTypeHandler { @@ -1404,7 +1404,7 @@ public class GenericTypeHandler extends BaseTypeHandler { EnumTypeHandler 来把 Enum 值转换成对应的名字。

    注意 EnumTypeHandler - 在某种意义上来说是比较特别的,其他的处理器只针对某个特定的类,而它不同,它会处理任意继承了 + 在某种意义上来说是比较特别的,其它的处理器只针对某个特定的类,而它不同,它会处理任意继承了 Enum 的类。

    不过,我们可能不想存储名字,相反我们的 DBA 会坚持使用整形值代码。那也一样简单:在配置文件中把 @@ -1551,13 +1551,13 @@ public class ExamplePlugin implements Interceptor {

    提示 覆盖配置类

    -

    除了用插件来修改 MyBatis 核心行为以外,还可以通过完全覆盖配置类来达到目的。只需继承后覆盖其中的某个方法,再把它传递到 SqlSessionFactoryBuilder.build(myConfig) 方法即可。再次重申,这可能会严重影响 MyBatis 的行为,务请慎之又慎。

    +

    除了用插件来修改 MyBatis 核心行为以外,还可以通过完全覆盖配置类来达到目的。只需继承配置类后覆盖其中的某个方法,再把它传递到 SqlSessionFactoryBuilder.build(myConfig) 方法即可。再次重申,这可能会极大影响 MyBatis 的行为,务请慎之又慎。

    MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, - 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中 - 使用相同的 SQL 映射。有许多类似的使用场景。

    + 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema + 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。

    不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。 @@ -1619,7 +1619,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert

    - 默认环境和环境 ID 顾名思义,一目了然。 + 默认环境和环境 ID 顾名思义。 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。

    @@ -1639,8 +1639,9 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert

    - 提示如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器, - 因为 Spring 模块会使用自带的管理器来覆盖前面的配置。 + 提示 + 如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 + Spring 模块会使用自带的管理器来覆盖前面的配置。

    这两种事务管理器类型都不需要设置任何属性。它们其实是类型别名,换句话说,你可以用 @@ -1653,8 +1654,8 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert Transaction newTransaction(Connection conn); Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit); }]]> -

    任何在 XML 中配置的属性在实例化之后将会被传递给 setProperties() - 方法。你也需要创建一个 Transaction 接口的实现类,这个接口也很简单:

    +

    在事务管理器实例化后,所有在 XML 中配置的属性将会被传递给 setProperties() + 方法。你的实现还需要创建一个 Transaction 接口的实现类,这个接口也很简单:

    dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

    • 大多数 MyBatis - 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但为了使用延迟加载,必须配置数据源。 + 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。

    有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):

    - UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对于对数据库连接可用性没有太高要求的简单应用程序来说,是一个很好的选择。 - 不同的数据库在性能方面的表现也是不一样的,对于某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。UNPOOLED 类型的数据源具有以下属性。:

    + UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 + 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。UNPOOLED 类型的数据源仅仅需要配置以下 5 种属性:

    • driver – 这是 JDBC 驱动的 Java 类全限定名(并不是 JDBC 驱动中可能包含的数据源类)。
    • @@ -1710,7 +1711,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert
    • poolMaximumCheckoutTime – 在被强制返回之前,池中连接被检出(checked out)时间,默认值:20000 毫秒(即 20 秒)
    • -
    • poolTimeToWait – 这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直安静的失败),默认值:20000 毫秒(即 20 秒)。 +
    • poolTimeToWait – 这是一个底层设置,如果获取连接花费了相当长的时间,连接池会打印状态日志并重新尝试获取一个连接(避免在误配置的情况下一直失败且不打印日志),默认值:20000 毫秒(即 20 秒)。
    • poolMaximumLocalBadConnectionTolerance – 这是一个关于坏连接容忍度的底层设置, 作用于每一个尝试从缓存池获取连接的线程。 @@ -1725,7 +1726,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert

    - JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。这种数据源配置只需要两个属性: + JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。这种数据源配置只需要两个属性:

    • initial_context – 这个属性用来在 InitialContext 中寻找上下文(即,initialContext.lookup(initial_context))。这是个可选属性,如果忽略,那么将会直接从 InitialContext 中寻找 data_source 属性。 @@ -1742,7 +1743,7 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert

      - 你可以通过实现接口 org.apache.ibatis.datasource.DataSourceFactory 来使用第三方数据源: + 你可以通过实现接口 org.apache.ibatis.datasource.DataSourceFactory 来使用第三方数据源实现:

      MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 - MyBatis 会加载带有匹配当前数据库 databaseId 属性和不带 databaseId 属性的所有语句。 + MyBatis 会加载带有匹配当前数据库 databaseId 属性和所有不带 databaseId 属性的语句。 如果同时找到带有 databaseId 和不带 databaseId 的相同语句,则后者会被舍弃。 为支持多厂商特性,只要像下面这样在 mybatis-config.xml 文件中加入 databaseIdProvider 即可:

      @@ -1826,7 +1827,7 @@ public class C3P0DataSourceFactory extends UnpooledDataSourceFactory { 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 - 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 的 URL),或类名和包名等。例如: + 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。例如:

      @@ -1854,7 +1855,7 @@ public class C3P0DataSourceFactory extends UnpooledDataSourceFactory { ]]> -

      这些配置会告诉了 MyBatis 去哪里找映射文件,剩下的细节就应该是每个 SQL +

      这些配置会告诉 MyBatis 去哪里找映射文件,剩下的细节就应该是每个 SQL 映射文件了,也就是接下来我们要讨论的。

    diff --git a/src/site/zh/xdoc/getting-started.xml b/src/site/zh/xdoc/getting-started.xml index 488faf33046..b73f120d319 100644 --- a/src/site/zh/xdoc/getting-started.xml +++ b/src/site/zh/xdoc/getting-started.xml @@ -46,16 +46,16 @@

    每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder - 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 - Configuration 的实例构建出 SqlSessionFactory 的实例。 + 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 + Configuration 实例来构建出 SqlSessionFactory 实例。

    从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。 - 但是也可以使用任意的输入流(InputStream)实例,比如从字符串形式的文件路径或者 - file:// 的 URL 形式的文件路径中构造而来的输入流。MyBatis 包含一个名叫 Resources - 的工具类,它包含一些实用方法,能让从类路径或其它位置加载资源文件更加容易。 + 但也可以使用任意的输入流(InputStream)实例,比如用文件路径字符串或 + file:// URL 构造的输入流。MyBatis 包含一个名叫 Resources + 的工具类,它包含一些实用方法,使得从类路径或其它位置加载资源文件更加容易。

    XML 配置文件中包含了对 MyBatis - 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)。 - XML 配置文件的详细内容后面再探讨,这里先给出一个简单的示例: + 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。后面会再探讨 + XML 配置文件的详细内容,这里先给出一个简单的示例:

    @@ -89,9 +89,9 @@ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input ]]>

    - 当然,还有很多设置可以在 XML 文件中进行配置,上面的示例罗列的是最关键的部分。 - 要注意 XML 头部的声明,它用来验证 XML 文档正确性。environment - 元素体中包含了事务管理和连接池的配置。mappers 元素则是包含一组映射器(mapper),这些映射器的 + 当然,还有很多可以在 XML 文件中配置的选项,上面的示例仅罗列了最关键的部分。 + 注意 XML 头部的声明,它用来验证 XML 文档的正确性。environment + 元素体中包含了事务管理和连接池的配置。mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。

    @@ -99,8 +99,8 @@ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input

    - 如果你更愿意直接从 Java 代码而不是 XML 文件中创建配置,或者想要创建你自己的配置构建器,MyBatis - 也提供了完整的配置类,提供所有和 XML 文件相同功能的配置项。 + 如果你更愿意直接从 Java 代码而不是 XML 文件中创建配置,或者想要创建你自己的配置建造器,MyBatis + 也提供了完整的配置类,提供了所有与 XML 文件等价的配置项。

    - 既然有了 SqlSessionFactory,顾名思义,我们就可以从中获得 SqlSession 的实例了。SqlSession - 完全包含了面向数据库执行 SQL 命令所需的所有方法。你可以通过 + 既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。SqlSession + 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。例如:

    @@ -131,10 +131,9 @@ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(confi Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101); }]]>

    - 诚然,这种方式能够正常工作,并且对于使用旧版本 MyBatis - 的用户来说也比较熟悉。不过现在有了一种更简洁的方式 - ——使用正确匹配每个语句的参数和返回值的接口(比如 - BlogMapper.class),现在你不仅可以执行更清晰和类型更安全的代码,而且还不用担心可能出错的字符串字面值以及强制类型转换。

    + 诚然,这种方式能够正常工作,对使用旧版本 MyBatis + 的用户来说也比较熟悉。但现在有了一种更简洁的方式——使用和指定语句的参数和返回值相匹配的接口(比如 + BlogMapper.class),现在你的代码不仅更清晰,更加类型安全,还不用担心可能出错的字符串字面值以及强制类型转换。

    例如:

    @@ -142,21 +141,21 @@ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(confi BlogMapper mapper = session.getMapper(BlogMapper.class); Blog blog = mapper.selectBlog(101); }]]> -

    现在我们来探究一下这里到底是怎么执行的。

    +

    现在我们来探究一下这段代码究竟做了些什么。

    - 现在你可能很想知道 SqlSession 和 Mapper 到底执行了什么操作,但 SQL - 语句映射是个相当大的话题,可能会占去文档的大部分篇幅。 - 不过为了让你能够了解个大概,这里会给出几个例子。 + 现在你可能很想知道 SqlSession 和 Mapper 到底具体执行了些什么操作,但 SQL + 语句映射是个相当广泛的话题,可能会占去文档的大部分篇幅。 + 但为了让你能够了解个大概,这里会给出几个例子。

    在上面提到的例子中,一个语句既可以通过 XML 定义,也可以通过注解定义。我们先看看 XML 定义语句的方式,事实上 MyBatis 提供的所有特性都可以利用基于 XML 的映射语言来实现,这使得 - MyBatis 在过去的数年间得以流行。如果你以前用过 MyBatis,你应该对这个概念比较熟悉。 - 不过自那以后,XML 的配置也改进了许多,我们稍后还会再提到。这里给出一个基于 XML - 映射语句的示例,它应该可以满足上述示例中 SqlSession 的调用。 + MyBatis 在过去的数年间得以流行。如果你用过旧版本的 MyBatis,你应该对这个概念比较熟悉。 + 但相比于之前的版本,新版本改进了许多 XML 的配置,后面我们会提到这些改进。这里给出一个基于 XML + 映射语句的示例,它应该可以满足上个示例中 SqlSession 的调用。

    @@ -170,20 +169,20 @@ SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(confi ]]>

    - 为了这个简单的例子,我们似乎写了不少配置,但实际上并不多。在一个 + 为了这个简单的例子,我们似乎写了不少配置,但其实并不多。在一个 XML 映射文件中,可以定义无数个映射语句,这样一来,XML - 头部和文档类型声明占去的部分就显得微不足道了。而文件的剩余部分具备自解释性,很容易理解。 - 在命名空间 “org.mybatis.example.BlogMapper” 中定义了一个名为 “selectBlog” - 的映射语句,允许你使用全限定名 - “org.mybatis.example.BlogMapper.selectBlog” 来调用映射语句,就像上面例子中那样: + 头部和文档类型声明部分就显得微不足道了。文档的其它部分很直白,容易理解。 + 它在命名空间 “org.mybatis.example.BlogMapper” 中定义了一个名为 “selectBlog” + 的映射语句,这样你就可以用全限定名 + “org.mybatis.example.BlogMapper.selectBlog” 来调用映射语句了,就像上面例子中那样:

    - 你可能会注意到这和使用全限定名调用 Java + 你可能会注意到,这种方式和用全限定名调用 Java 对象的方法类似。这样,该命名就可以直接映射到在命名空间中同名的映射器类,并将已映射的 - select 语句匹配到对应名字、参数和返回类型的方法。因此你就可以像上面那样很容易地调用这个对应映射器接口的方法,就像下面这样: + select 语句匹配到对应名称、参数和返回类型的方法。因此你就可以像上面那样,不费吹灰之力地在对应的映射器接口调用方法,就像下面这样:

    第二种方法有很多优势,首先它不依赖于字符串字面值,会更安全一点;其次,如果你的 - IDE 有代码补全功能,那么代码补全可以帮你快速选择已映射的 SQL 语句。 + IDE 有代码补全功能,那么代码补全可以帮你快速选择到映射好的 SQL 语句。


    -

    提示对命名空间的一点说明

    +

    提示 + 对命名空间的一点补充

    在之前版本的 MyBatis 中,命名空间(Namespaces)的作用并不大,是可选的。 @@ -209,23 +209,23 @@ Blog blog = mapper.selectBlog(101);]]>

    命名解析:为了减少输入量,MyBatis - 对所有的命名配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。 + 对所有具有名称的配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。

      -
    • 完全限定名(比如 +
    • 全限定名(比如 “com.mypackage.MyMapper.selectAllThings)将被直接用于查找及使用。
    • 短名称(比如 “selectAllThings”)如果全局唯一也可以作为一个单独的引用。 如果不唯一,有两个或两个以上的相同名称(比如 “com.foo.selectAllThings” 和 - “com.bar.selectAllThings”),那么使用时就会产生“短名称不唯一”的错误,这种情况下就必须使用完全限定名。 + “com.bar.selectAllThings”),那么使用时就会产生“短名称不唯一”的错误,这种情况下就必须使用全限定名。

    - 对于像 BlogMapper 这样的映射器类来说,还有另一种方法来处理映射。 + 对于像 BlogMapper 这样的映射器类来说,还有另一种方法来完成语句映射。 它们映射的语句可以不用 XML 来配置,而可以使用 Java 注解来配置。比如,上面的 XML - 示例可被替换如下: + 示例可以被替换成如下的配置:

    - 使用注解来映射简单语句会使代码显得更加简洁,然而对于稍微复杂一点的语句,Java - 注解就力不从心了,并且会显得更加混乱。 - 因此,如果你需要完成很复杂的事情,那么最好使用 XML 来映射语句。 + 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java + 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 + 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。

    - 选择何种方式来配置映射,以及认为映射语句定义的一致性是否重要,这些完全取决于你和你的团队。 + 选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。 换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。

    -

    理解我们目前已经讨论过的不同作用域和生命周期类是至关重要的,因为错误的使用会导致非常严重的并发问题。

    +

    理解我们之前讨论过的不同作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。


    提示 @@ -253,7 +253,7 @@ public interface BlogMapper {

    依赖注入框架可以创建线程安全的、基于事务的 SqlSession 和映射器,并将它们直接注入到你的 bean 中,因此可以直接忽略它们的生命周期。 - 如果对如何通过依赖注入框架来使用 MyBatis 感兴趣,可以研究一下 MyBatis-Spring + 如果对如何通过依赖注入框架使用 MyBatis 感兴趣,可以研究一下 MyBatis-Spring 或 MyBatis-Guice 两个子项目。


    SqlSessionFactoryBuilder

    @@ -261,13 +261,13 @@ public interface BlogMapper { 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory - 实例,但是最好还是不要让其一直存在,以保证所有的 XML 解析资源可以被释放给更重要的事情。 + 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

    SqlSessionFactory

    SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 - SqlSessionFactory 被视为一种代码“坏味道”。因此 + SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

    @@ -277,25 +277,25 @@ public interface BlogMapper { 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 - 如果你现在正在使用一种 Web 框架,要考虑 SqlSession 放在一个和 HTTP 请求对象相似的作用域中。 - 换句话说,每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它。 + 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 + 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:

    -

    在你的所有的代码中一致地使用这种模式来保证所有数据库资源都能被正确地关闭。

    +

    在所有代码中都遵循这种使用模式,可以保证所有数据库资源都能被正确地关闭。

    映射器实例

    - 映射器是一些由你创建的绑定映射语句的接口。映射器接口的实例是从 - SqlSession 中获得的。因此从技术层面讲,任何映射器实例的最大作用域与请求它们的 - SqlSession 相同。尽管如此,映射器实例的最佳作用域是方法作用域。 - 也就是说,映射器实例应该在调用它们的方法中被请求,使用完毕之后即可丢弃。 - 映射器实例并不需要被显式地关闭。尽管在整个请求作用域保留映射器实例不会有什么问题,但是你很快会发现,像 - SqlSession 一样,在这个作用域上管理太多的资源会难以控制。 - 为了避免这种复杂性,最好把映射器放在方法作用域内。下面的示例就展示了这个实践: + 映射器是一些绑定映射语句的接口。映射器接口的实例是从 + SqlSession 中获得的。虽然从技术层面上来讲,任何映射器实例的最大作用域与请求它们的 + SqlSession 相同。但方法作用域才是映射器实例的最合适的作用域。 + 也就是说,映射器实例应该在调用它们的方法中被获取,使用完毕之后即可丢弃。 + 映射器实例并不需要被显式地关闭。尽管在整个请求作用域保留映射器实例不会有什么问题,但是你很快会发现,在这个作用域上管理太多像 + SqlSession 的资源会让你忙不过来。 + 因此,最好将映射器放在方法作用域内。就像下面的例子一样:

    @@ -734,9 +733,9 @@ public class User { ]]>

    - 这些情况下,MyBatis 会在幕后自动创建一个 ResultMap,再基于属性名来映射列到 - JavaBean 的属性上。如果列名和属性名没有精确匹配,可以在 SELECT - 语句中对列使用别名(这是一个基本的 SQL 特性)来匹配标签。比如: + 在这些情况下,MyBatis 会在幕后自动创建一个 ResultMap,再根据属性名来映射列到 + JavaBean 的属性上。如果列名和属性名不能匹配上,可以在 SELECT + 语句中设置列别名(这是一个基本的 SQL 特性)来完成匹配。比如:

    @@ -749,9 +748,11 @@ public class User { ]]>

    - ResultMap 最优秀的地方在于,虽然你已经对它相当了解了,但是根本就不需要显式地用到他们。 - 上面这些简单的示例根本不需要下面这些繁琐的配置。 - 但出于示范的原因,让我们来看看最后一个示例中,如果使用外部的 + 在学习了上面的知识后,你会发现上面的例子没有一个需要显式配置 + ResultMap,这就是 ResultMap + 的优秀之处——你完全可以不用显式地配置它们。 + 虽然上面的例子不用显式配置 ResultMap。 + 但为了讲解,我们来看看如果在刚刚的示例中,显式使用外部的 resultMap 会怎样,这也是解决列名不匹配的另外一种方式。

    @@ -762,7 +763,7 @@ public class User { ]]>

    - 而在引用它的语句中使用 resultMap 属性就行了(注意我们去掉了 + 然后在引用它的语句中设置 resultMap 属性就行了(注意我们去掉了 resultType 属性)。比如:

    @@ -773,15 +774,15 @@ public class User { ]]>

    - 如果世界总是这么简单就好了。 + 如果这个世界总是这么简单就好了。

    高级结果映射

    MyBatis 创建时的一个思想是:数据库不可能永远是你所想或所需的那个样子。 - 我们希望每个数据库都具备良好的第三范式或 BCNF 范式,可惜它们不总都是这样。 - 如果能有一种完美的数据库映射模式,所有应用程序都可以使用它,那就太好了,但可惜也没有。 + 我们希望每个数据库都具备良好的第三范式或 BCNF 范式,可惜它们并不都是那样。 + 如果能有一种数据库映射模式,完美适配所有的应用程序,那就太好了,但可惜也没有。 而 ResultMap 就是 MyBatis 对这个问题的答案。

    @@ -826,8 +827,8 @@ public class User {

    你可能想把它映射到一个智能的对象模型,这个对象表示了一篇博客,它由某位作者所写,有很多的博文,每篇博文有零或多条的评论和标签。 - 我们来看看下面这个完整的例子,它是一个非常复杂的结果映射(假设作者,博客,博文,评论和标签都是类型别名)。 - 不用紧张,我们会一步一步来说明。虽然它看起来令人望而生畏,但其实非常简单。 + 我们先来看看下面这个完整的例子,它是一个非常复杂的结果映射(假设作者,博客,博文,评论和标签都是类型别名)。 + 不用紧张,我们会一步一步地来说明。虽然它看起来令人望而生畏,但其实非常简单。

    @@ -879,13 +880,13 @@ public class User {
  • association – 一个复杂类型的关联;许多结果将包装成这种类型
      -
    • 嵌套结果映射 – 关联本身可以是一个 resultMap 元素,或者从别处引用一个
    • +
    • 嵌套结果映射 – 关联可以是 resultMap 元素,或是对其它结果映射的引用
  • collection – 一个复杂类型的集合
      -
    • 嵌套结果映射 – 集合本身可以是一个 resultMap 元素,或者从别处引用一个
    • +
    • 嵌套结果映射 – 集合可以是 resultMap 元素,或是对其它结果映射的引用
  • @@ -894,7 +895,7 @@ public class User {
  • case – 基于某些值的结果映射
      -
    • 嵌套结果映射 – case 本身可以是一个 resultMap 元素,因此可以具有相同的结构和元素,或者从别处引用一个
    • +
    • 嵌套结果映射 – case 也是一个结果映射,因此具有相同的结构和元素;或者引用其它的结果映射
  • @@ -923,7 +924,7 @@ public class User { autoMapping - 如果设置这个属性,MyBatis将会为本结果映射开启或者关闭自动映射。 + 如果设置这个属性,MyBatis 将会为本结果映射开启或者关闭自动映射。 这个属性会覆盖全局的属性 autoMappingBehavior。默认值:未设置(unset)。 @@ -932,12 +933,11 @@ public class User {

    最佳实践 - 最好一步步地建立结果映射。单元测试可以在这个过程中起到很大帮助。 - 如果你尝试一次创建一个像上面示例那样的巨大的结果映射,那么很可能会出现错误而且很难去使用它来完成工作。 - 从最简单的形态开始,逐步迭代。而且别忘了单元测试! - 使用框架的缺点是有时候它们看上去像黑盒子(无论源代码是否可见)。 - 为了确保你实现的行为和想要的一致,最好的选择是编写单元测试。提交 bug - 的时候它也能起到很大的作用。 + 最好逐步建立结果映射。单元测试可以在这个过程中起到很大帮助。 + 如果你尝试一次性创建像上面示例那么巨大的结果映射,不仅容易出错,难度也会直线上升。 + 所以,从最简单的形态开始,逐步迭代。而且别忘了单元测试! + 有时候,框架的行为像是一个黑盒子(无论是否开源)。因此,为了确保实现的行为与你的期望相一致,最好编写单元测试。 + 并且单元测试在提交 bug 时也能起到很大的作用。

    @@ -950,14 +950,14 @@ public class User { ]]>

    - 这些是结果映射最基本的内容。idresult + 这些元素是结果映射的基础。idresult 元素都将一个列的值映射到一个简单数据类型(String, int, double, Date 等)的属性或字段。

    这两者之间的唯一不同是,id - 元素表示的结果将是对象的标识属性,这会在比较对象实例时用到。 + 元素对应的属性会被标记为对象的标识符,在比较对象实例时使用。 这样可以提高整体的性能,尤其是进行缓存和嵌套结果映射(也就是连接映射)的时候。

    @@ -977,9 +977,9 @@ public class User { property - 映射到列结果的字段或属性。如果用来匹配的 JavaBean - 存在给定名字的属性,那么它将会被使用。否则 MyBatis 将会寻找给定名称的字段。 - 无论是哪一种情形,你都可以使用通常的点式分隔形式进行复杂属性导航。 + 映射到列结果的字段或属性。如果 JavaBean + 有这个名字的属性(property),会先使用该属性。否则 MyBatis 将会寻找给定名称的字段(field)。 + 无论是哪一种情形,你都可以使用常见的点式分隔形式进行复杂属性导航。 比如,你可以这样映射一些简单的东西:“username”,或者映射到一些复杂的东西上:“address.street.number”。 @@ -993,7 +993,7 @@ public class User { javaType - 一个 Java 类的完全限定名,或一个类型别名(关于内置的类型别名,可以参考上面的表格)。 + 一个 Java 类的全限定名,或一个类型别名(关于内置的类型别名,可以参考上面的表格)。 如果你映射到一个 JavaBean,MyBatis 通常可以推断类型。然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证行为与期望的相一致。 @@ -1004,14 +1004,14 @@ public class User { JDBC 类型,所支持的 JDBC 类型参见这个表格之后的“支持的 JDBC 类型”。 只需要在可能执行插入、更新和删除的且允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。如果你直接面向 JDBC - 编程,你需要对可能存在空值的列指定这个类型。 + 编程,你需要对可以为空值的列指定这个类型。 typeHandler 我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的类型处理器。 - 这个属性值是一个类型处理器实现类的完全限定名,或者是类型别名。 + 这个属性值是一个类型处理器实现类的全限定名,或者是类型别名。 diff --git a/src/site/zh/xdoc/statement-builders.xml b/src/site/zh/xdoc/statement-builders.xml index 74b7824cab1..3dcb3e74fce 100644 --- a/src/site/zh/xdoc/statement-builders.xml +++ b/src/site/zh/xdoc/statement-builders.xml @@ -28,7 +28,7 @@
    -

    Java 程序员面对的最痛苦的事情之一就是在 Java 代码中嵌入 SQL 语句。这通常是因为需要动态生成 SQL 语句,不然我们可以将它们放到外部文件或者存储过程中。正如你已经看到的,MyBatis 在 XML 映射功能中有一个强大的 SQL 动态生成解决方案。但有时,我们还是需要在 Java 代码里构建 SQL 语句。此时,MyBatis 有另外一个特性可以帮到你,从而让你从处理典型问题中解放出来,比如加号、引号、换行、格式化问题、嵌入条件的逗号管理及 AND 连接。确实,在 Java 代码中动态生成 SQL 代码真的就是一场噩梦。例如: +

    Java 程序员面对的最痛苦的事情之一就是在 Java 代码中嵌入 SQL 语句。这通常是因为需要动态生成 SQL 语句,不然我们可以将它们放到外部文件或者存储过程中。如你所见,MyBatis 在 XML 映射中具备强大的 SQL 动态生成能力。但有时,我们还是需要在 Java 代码里构建 SQL 语句。此时,MyBatis 有另外一个特性可以帮到你,让你从处理典型问题中解放出来,比如加号、引号、换行、格式化问题、嵌入条件的逗号管理及 AND 连接。确实,在 Java 代码中动态生成 SQL 代码真的就是一场噩梦。例如:

    -

    这个例子有什么特别的地方吗?仔细看一下你会发现,你不用担心可能会重复出现的 "AND" 关键字,或者要做出用 "WHERE" 还是 "AND" 还是不用拼接的选择。SQL 类已经为你处理了哪里应该插入 "WHERE"、哪里应该使用 "AND" 的问题,并帮你完成所有的字符串拼接工作。 +

    这个例子有什么特别之处吗?仔细看一下你会发现,你不用担心可能会重复出现的 "AND" 关键字,或者要做出用 "WHERE" 拼接还是 "AND" 拼接还是不用拼接的选择。SQL 类已经为你处理了哪里应该插入 "WHERE"、哪里应该使用 "AND" 的问题,并帮你完成所有的字符串拼接工作。

    @@ -520,7 +520,7 @@ public String selectPersonsWithFetchFirstSql() {

    - 在版本 3.2 之前,我们采取了不太一样的措施,通过使用 ThreadLocal 变量来掩盖一些对 Java DSL 不太友好的语言限制。这种方式已被废弃,在这个领域,人们已经对现代框架使用的构建器模式和匿名内部类模式习以为常了。因此,SelectBuilder 和 SqlBuilder 类都被废弃了。 + 在版本 3.2 之前,我们的实现方式不太一样,我们利用 ThreadLocal 变量来掩盖一些对 Java DSL 不太友好的语言限制。现在,现代 SQL 构建框架使用的构建器和匿名内部类思想已被人们所熟知。因此,我们废弃了基于这种实现方式的 SelectBuilder 和 SqlBuilder 类。

    下面的方法仅仅适用于废弃的 SqlBuilder 和 SelectBuilder 类。 @@ -553,7 +553,7 @@ public String selectPersonsWithFetchFirstSql() {

    - 虽然 SelectBuilder 和 SqlBuilder 类并不神奇,但是知道它们的工作原理也是很重要的。 + SelectBuilder 和 SqlBuilder 类并不神奇,但最好还是知道它们的工作原理。 SelectBuilder 以及 SqlBuilder 借助静态导入和 ThreadLocal 变量实现了对插入条件友好的简洁语法。要使用它们,只需要静态导入这个类的方法即可,就像这样(只能使用其中的一条,不能同时使用):

    From d15936e41ce47888e4040fc62f3e236edf26651c Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 12 Jan 2020 11:33:09 +0800 Subject: [PATCH 8/9] Update upstream docs --- src/site/zh/xdoc/configuration.xml | 12 ++++----- src/site/zh/xdoc/java-api.xml | 15 ++++++----- src/site/zh/xdoc/statement-builders.xml | 36 ++++++++++++------------- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/site/zh/xdoc/configuration.xml b/src/site/zh/xdoc/configuration.xml index d560a7d0be8..0df9c2c2b82 100644 --- a/src/site/zh/xdoc/configuration.xml +++ b/src/site/zh/xdoc/configuration.xml @@ -321,13 +321,13 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ defaultResultSetType - Specifies a scroll strategy when omit it per statement settings. (Since: 3.5.2) + 指定语句默认的滚动策略。(新增于 3.5.2) - FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(same behavior with 'Not Set') + FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置) - Not Set (null) + 未设置 (null) @@ -1648,8 +1648,8 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, propert TransactionFactory 接口实现类的全限定名或类型别名代替它们。

  • defaultTransactionIsolationLevel – 默认的连接事务隔离级别。
  • -
  • defaultNetworkTimeout – The default network timeout value in milliseconds to wait for the database operation to complete. See the API documentation of java.sql.Connection#setNetworkTimeout() for details. +
  • defaultNetworkTimeout – 等待数据库操作完成的默认网络超时时间(单位:毫秒)。查看 java.sql.Connection#setNetworkTimeout() 的 API 文档以获取更多信息。
  • 作为可选项,你也可以传递属性给数据库驱动。只需在属性名加上“driver.”前缀即可,例如: diff --git a/src/site/zh/xdoc/java-api.xml b/src/site/zh/xdoc/java-api.xml index 4de851b8b0e..178042f281a 100644 --- a/src/site/zh/xdoc/java-api.xml +++ b/src/site/zh/xdoc/java-api.xml @@ -71,7 +71,7 @@

    提示 当 Mybatis 与一些依赖注入框架(如 Spring 或者 Guice)搭配使用时,SqlSession 将被依赖注入框架创建并注入,所以你不需要使用 SqlSessionFactoryBuilder 或者 SqlSessionFactory,可以直接阅读 SqlSession 这一节。请参考 Mybatis-Spring 或者 Mybatis-Guice 手册以了解更多信息。

    SqlSessionFactoryBuilder

    -

    SqlSessionFactoryBuilder 有五个 build() 方法,每一种都允许你从不同的资源中创建一个 SqlSession 实例。

    +

    SqlSessionFactoryBuilder 有五个 build() 方法,每一种都允许你从不同的资源中创建一个 SqlSessionFactory 实例。

    SqlSessionFactory build(InputStream inputStream) SqlSessionFactory build(InputStream inputStream, String environment) SqlSessionFactory build(InputStream inputStream, Properties properties) @@ -350,7 +350,7 @@ try (SqlSession session = sqlSessionFactory.openSession()) {
  • <idArg>
  • -        ConstructorArgs 集合的一部分,代表一个构造方法参数。属性:idcolumnjavaTypejdbcTypetypeHandlerselectresultMap。id 属性和 XML 元素 <idArg> 相似,它是一个布尔值,表示该属性是否用于唯一标识和比较对象。 +        ConstructorArgs 集合的一部分,代表一个构造方法参数。属性:idcolumnjavaTypejdbcTypetypeHandlerselectresultMap。id 属性和 XML 元素 <idArg> 相似,它是一个布尔值,表示该属性是否用于唯一标识和比较对象。从版本 3.5.4 开始,该注解变为可重复注解。 @TypeDiscriminator @@ -368,7 +368,7 @@ try (SqlSession session = sqlSessionFactory.openSession()) { @Results 方法 <resultMap> - 一组结果映射,指定了对某个特定结果列,映射到某个属性或字段的方式。属性:valueid。value 属性是一个 Result 注解的数组。而 id 属性则是结果映射的名称。 + 一组结果映射,指定了对某个特定结果列,映射到某个属性或字段的方式。属性:valueid。value 属性是一个 Result 注解的数组。而 id 属性则是结果映射的名称。从版本 3.5.4 开始,该注解变为可重复注解。 @Result @@ -444,7 +444,7 @@ try (SqlSession session = sqlSessionFactory.openSession()) {
  • <select>
  • -        允许构建动态 SQL。这些备选的 SQL 注解允许你指定返回 SQL 语句的类和方法,以供运行时执行。(从 MyBatis 3.4.6 开始,可以使用 CharSequence 代替 String 来作为返回类型)。当执行映射语句时,MyBatis 会实例化注解指定的类,并调用注解指定的方法。你可以通过 ProviderContext 传递映射方法接收到的参数、"Mapper interface type" 和 "Mapper method"(仅在 MyBatis 3.4.5 以上支持)作为参数。(MyBatis 3.4 以上支持传入多个参数)属性:typemethodtype 属性用于指定类名。method 用于指定该类的方法名。提示 接下来的“SQL 语句构建器”一章将会讨论该话题,以帮助你以更清晰、更便于阅读的方式构建动态 SQL。 +        允许构建动态 SQL。这些备选的 SQL 注解允许你指定返回 SQL 语句的类和方法,以供运行时执行。(从 MyBatis 3.4.6 开始,可以使用 CharSequence 代替 String 来作为返回类型)。当执行映射语句时,MyBatis 会实例化注解指定的类,并调用注解指定的方法。你可以通过 ProviderContext 传递映射方法接收到的参数、"Mapper interface type" 和 "Mapper method"(仅在 MyBatis 3.4.5 以上支持)作为参数。(MyBatis 3.4 以上支持传入多个参数)属性:typemethodtype 属性用于指定类名。method 用于指定该类的方法名(从版本 3.5.1 开始,可以忽略 method 属性,MyBatis 将会使用 ProviderMethodResolver 接口解析方法的具体实现。如果解析失败,MyBatis 将会使用名为 provideSql 的降级实现)。提示 接下来的“SQL 语句构建器”一章将会讨论该话题,以帮助你以更清晰、更便于阅读的方式构建动态 SQL。 @Param @@ -552,13 +552,14 @@ class UserSqlBuilder { } }]]> -

    This example shows usage the default implementation of ProviderMethodResolver(available since MyBatis 3.5.1 or later):

    +

    以下例子展示了 ProviderMethodResolver(3.5.1 后可用)的默认实现使用方法: +

    getUsersByName(String name); -// Implements the ProviderMethodResolver on your provider class +// 在你的 provider 类中实现 ProviderMethodResolver 接口 class UserSqlProvider implements ProviderMethodResolver { - // In default implementation, it will resolve a method that method name is matched with mapper method + // 默认实现中,会将映射器方法的调用解析到实现的同名方法上 public static String getUsersByName(final String name) { return new SQL(){{ SELECT("*"); diff --git a/src/site/zh/xdoc/statement-builders.xml b/src/site/zh/xdoc/statement-builders.xml index 3dcb3e74fce..b4c0a53ce08 100644 --- a/src/site/zh/xdoc/statement-builders.xml +++ b/src/site/zh/xdoc/statement-builders.xml @@ -313,9 +313,9 @@ public String updatePersonSql() { - Appends a LIMIT clause. - This method valid when use together with SELECT(), UPDATE() and DELETE(). - And this method is designed to use together with OFFSET() when use SELECT(). (Available since 3.5.2) + 追加新的 LIMIT 子句。 + 仅在 SELECT()、UPDATE()、DELETE() 时有效。 + 当在 SELECT() 中使用时,应该配合 OFFSET() 使用。(于 3.5.2 引入) @@ -330,9 +330,9 @@ public String updatePersonSql() { - Appends a OFFSET clause. - This method valid when use together with SELECT(). - And this method is designed to use together with LIMIT(). (Available since 3.5.2) + 追加新的 OFFSET 子句。 + 仅在 SELECT() 时有效。 + 当在 SELECT() 时使用时,应该配合 LIMIT() 使用。(于 3.5.2 引入) @@ -347,9 +347,9 @@ public String updatePersonSql() { - Appends a OFFSET n ROWS clause. - This method valid when use together with SELECT(). - And this method is designed to use together with FETCH_FIRST_ROWS_ONLY(). (Available since 3.5.2) + 追加新的 OFFSET n ROWS 子句。 + 仅在 SELECT() 时有效。 + 该方法应该配合 FETCH_FIRST_ROWS_ONLY() 使用。(于 3.5.2 加入) @@ -364,9 +364,9 @@ public String updatePersonSql() { - Appends a FETCH FIRST n ROWS ONLY clause. - This method valid when use together with SELECT(). - And this method is designed to use together with OFFSET_ROWS(). (Available since 3.5.2) + 追加新的 FETCH FIRST n ROWS ONLY 子句。 + 仅在 SELECT() 时有效。 + 该方法应该配合 OFFSET_ROWS() 使用。(于 3.5.2 加入) @@ -431,18 +431,16 @@ public String updatePersonSql() { ADD_ROW() - Add new row for bulk insert. (Available since 3.5.2) + 添加新的一行数据,以便执行批量插入。(于 3.5.2 引入)

    - NOTE - It is important to note that SQL class writes LIMIT, OFFSET, OFFSET n ROWS and FETCH FIRST n ROWS ONLY clauses into the generated statement as is. - In other words, the library does not attempt to normalize those values for databases that don’t support these clauses directly. - Therefore, it is very important for users to understand whether or not the target database supports these clauses. - If the target database does not support these clauses, then it is likely that using this support will create SQL that has runtime errors. + 提示 + 注意,SQL 类将原样插入 LIMITOFFSETOFFSET n ROWS 以及 FETCH FIRST n ROWS ONLY 子句。换句话说,类库不会为不支持这些子句的数据库执行任何转换。 + 因此,用户应该要了解目标数据库是否支持这些子句。如果目标数据库不支持这些子句,产生的 SQL 可能会引起运行错误。

    从版本 3.4.2 开始,你可以像下面这样使用可变长度参数:

    @@ -474,7 +472,7 @@ public String updatePersonSql() { } ]]> -

    Since version 3.5.2, you can create insert statement for bulk insert as follow:

    +

    从版本 3.5.2 开始,你可以像下面这样构建批量插入语句:

    Date: Sun, 12 Jan 2020 16:37:15 +0800 Subject: [PATCH 9/9] Update untranslated and fix errors --- src/site/zh/xdoc/configuration.xml | 6 ++-- src/site/zh/xdoc/dynamic-sql.xml | 2 +- src/site/zh/xdoc/java-api.xml | 4 +-- src/site/zh/xdoc/logging.xml | 44 +++++++++++-------------- src/site/zh/xdoc/sqlmap-xml.xml | 2 +- src/site/zh/xdoc/statement-builders.xml | 4 +-- 6 files changed, 29 insertions(+), 33 deletions(-) diff --git a/src/site/zh/xdoc/configuration.xml b/src/site/zh/xdoc/configuration.xml index 0df9c2c2b82..c449db26aee 100644 --- a/src/site/zh/xdoc/configuration.xml +++ b/src/site/zh/xdoc/configuration.xml @@ -1,7 +1,7 @@