admin 管理员组

文章数量: 1184232


2024年1月17日发(作者:匿名管道和命名管道)

MyBatis用户指南中文版

version 3.2.2

MyBatis用户指南中文版

最近更新: 02 四月2013

Version: 3.2.2PDF Creator :Esin.z2013/04/10内容目录1简介........................................................................3什么是 MyBatis?...........................................................3Help make this documentation better….....................................3关于翻译..................................................................3入门........................................................................3从 XML 中构建 .3不使用 XML 构建 4从 SqlSessionFactory 中获取 .5探究已映射的 SQL 语句.....................................................5范围和生命周期............................................................7XML 映射配置文件.............................................................25Mapper XML 文件............................................................26

Copyright © 2010-2013 g . All Rights Reserved. 1/79

MyBatis用户指南中文版

version 3.2.2

27insert, update 49缓存.....................................................................50动态 53choose, when, 53trim, where, 56Multi-db 57Pluggable Scripting Languages For 58应用目录结构.............................................................77

Copyright © 2010-2013 g . All Rights Reserved. 2/79

MyBatis用户指南中文版

version 3.2.2

简介什么是 MyBatis?MyBatis

是支持普通

SQL

查询,存储过程和高级映射的优秀持久层框架。MyBatis

消除 了几乎所有的

JDBC

代码和参数的手工设置以及结果集的检索。MyBatis

使用简单的

XML

或注解用于配置和原始映射,将接口和

Java

POJOs(Plan Old Java Objects,普通的

Java

对象)映射成数据库中的记录。

Help make this documentation better…如果你发现了本文档的遗漏之处,

或者丢失

MyBatis

特性的说明时,

那么最好的方法就 是了解一下这个遗漏之处然后把它记录下来。

Sources of this manual are available in xdoc format at project's GitHub . Check

them out, update them and send your patch to the tracker .

你也是本文档的最佳作者,其他用户也会来阅读它的。

关于翻译MyBatis 3

的用户指南翻译由南磊完成,若对翻译质量有任何意见和建议,请联系

nanlei1987@,愿和大家共同提高,共同进步。

入门每 一 个

MyBatis

的 应 用 程 序 都 以 一 个

SqlSessionFactory

对 象 的 实 例 为 核 心 。SqlSessionFactory

对 象 的 实 例 可 以 通 过

SqlSessionFactoryBuilder

对 象 来 获 得 。

SqlSessionFactoryBuilder

对象可以从

XML

配置文件,或从

Configuration

类的习惯准备的实例中构建

SqlSessionFactory

对象。

从 XML 中构建 SqlSessionFactory从

XML

文件中构建

SqlSessionFactory

的实例非常简单。这里建议你使用类路径下的资 源文件来配置,但是你可以使用任意的

Reader

实例,这个实例包括由文字形式的文件路径 或

URL

形式的文件路径

file://来创建。MyBatis

包含了一些工具类,称作为资源,这些工具 类包含一些方法,这些方法使得从类路径或其他位置加载资源文件更加简单。

Copyright © 2010-2013 g . All Rights Reserved. 3/79

MyBatis用户指南中文版

version 3.2.2

String resource = "org/mybatis/example/";InputStream inputStream = ourceAsStream(resource);sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);XML

配置文件包含对

MyBatis

系统的核心设置,包含获取数据库连接实例的数据源和 决定事务范围和控制的事务管理器。关于

XML

配置文件的详细内容可以在文档后面找到,

这里给出一个简单的示例:

当然, XML

配置文件中还有很多可以配置的,

在 上面的示例指出的则是最关键的部分。 要注意

XML

头部的声明,需要用来验证

XML

文档正确性。environment

元素体中包含对事 务管理和连接池的环境配置。

mappers

元素是包含所有

mapper

映射器) (

的列表,

这些

mapper

XML

文件包含

SQL代码和映射定义信息。

不使用 XML 构建 SqlSessionFactory如果你喜欢从

Java

程序而不是

XML

文件中直接创建配置实例,

或创建你自己的配置构 建器,MyBatis

也提供完整的配置类,提供所有从

XML

文件中加载配置信息的选项。

DataSource dataSource = gDataSource();TransactionFactory transactionFactory = new JdbcTransactionFactory();Environment environment = new Environment("development", transactionFactory, dataSource);Configuration configuration = new Configuration(environment);per();SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);注意这种情况下配置是添加映射类。映射类是

Java

类,这些类包含

SQL

映射语句的注 解从而避免了

Copyright © 2010-2013 g . All Rights Reserved. 4/79

MyBatis用户指南中文版

version 3.2.2

XML

文件的依赖, XML

映射仍然在大多数高级映射

(比如:

嵌套

Join

映射)

时需要。出于这样的原因,如果存在

XML

配置文件的话,MyBatis

将会自动查找和加载一 个对等的

XML

文件(这种情况下,基于类路径下的

类的类名,那么

将会被加载)。后面我们会了解更多。

从 SqlSessionFactory 中获取 SqlSession现在,我们已经知道如何获取

SqlSessionFactory

对象了,基于同样的启示,我们就可以 获得

SqlSession

的实例了。

SqlSession

对象完全包含以数据库为背景的所有执行

SQL

操作的 方法。你可以用

SqlSession

实例来直接执行已映射的

SQL

语句。例如:

SqlSession session = ssion();try { Blog blog = (Blog) One("Blog", 101);} finally { ();}这种方法起到的作用,

和我们使用之前的

MyBatis

版本是相似的,

现在有一种更简洁的 方法。使用合理描述参数和

SQL

语句返回值的接口(比如

) ,这样现在就 可以至此那个更简单,更安全的代码,没有容易发生的字符串文字和转换的错误。

例如:

SqlSession session = ssion();try { BlogMapper mapper = per(); Blog blog = Blog(101);} finally { ();}现在我们来探究一下这里到底执行了什么。

探究已映射的 SQL 语句这里你也许想知道通过

SqlSession

Mapper

对象到底执行了什么操作。已映射的

SQL

语句是一个很大的主题,

而且这个主题会贯穿本文档的大部分内容。 为了给出一个宏观的概 念,这里有一些示例。 上面提到的任何一个示例,语句是通过

XML

或注解定义的。我们先来看看

XML。使 用基于

XML

的映射语言,在过去的几年中使得

MyBatis

非常流行,他为

MyBatis

提供所有 的特性设置。如果你以前用过

MyBatis,这个概念应该很熟悉了,但是

XML

映射文件也有 很多的改进,后面我们会详细来说。这里给出一个基于

XML

映射语句的示例,这些语句应 该可以满足上述示例中

SqlSession

对象的调用。

Copyright © 2010-2013 g . All Rights Reserved. 5/79

MyBatis用户指南中文版

version 3.2.2

这个简单的例子中看起来有很多额外的东西,

但是也相当简洁了。 你可以在一个单独的

XML

映射文件中定义很多的映射语句,除

XML

头部和文档类型声明之外,你可以得到很 多 方 便 之 处 。 在 文 件的 剩 余 部 分 是 很 好 的 自 我 解 释 。 在 命 名 空 间

“pper”中,它定义了一个名为“selectBlog”的映射语句,这 样它允许你使用完全限定名 “Blog”

来调用映射语句,

我们下面示例中所有的写法也是这样的。

Blog blog = (Blog) One("Blog", 101);要注意这个使用完全限定名调用

Java

对象的方法是相似的,这样做是有原因的。这个 命名可以直接给相同命名空间下的的映射类,

使用一个名称,

参数和返回值和已映射的查询 语句都一样的方法即可。

这就允许你非常容易地调用映射器接口中的方法,

这和你前面看到 的是一样的,下面这个示例中它又出现了。

BlogMapper mapper = per();Blog blog = Blog(101);第二种方式有很多有点,首先它不是基于文字的,那就更安全了。第二,如果你的

IDE

有代码补全功能,那么你可以利用它来操纵已映射的

SQL

语句。第三,不需要强制类型转 换,同时

BlogMapper

接口可以保持简洁,返回值类型很安全(参数类型也很安全)

重要 命名空间的一点注释

命名空间 在之前版本的

MyBatis

中是可选项,非常混乱也没有帮助。现在,命名空间 是必须的,而且有一个目的,它使用更长的完全限定名来隔离语句。

命名空间使得接口绑定成为可能,就像你看到的那样,如果之前不了解,那么现在你 就会使用它们了,你应该按照下面给出示例的来练习,以免改变自己的想法。使用命名空 间,并将它放在合适的

Java

包空间之下,将会使你的代码变得简洁,在很长的时间内提高

MyBatis

的作用。

命名解析:

为了减少输入量,MyBatis

对所有的命名配置元素使用如下的命名解析规 则,包括语句,结果映射,缓存等。

•直接查找完全限定名(比如“AllThings”,如果

)

发现就使用。

•短名称(比如“selectAllThings” )可以用来引用任意含糊的对象。而如果有两个 或两个以上的(比如“AllThings ”和“AllThings” ),

那么就会得到错误报告,说短名称是含糊的,因此就必须使用完全限定名。

Copyright © 2010-2013 g . All Rights Reserved. 6/79

MyBatis用户指南中文版

version 3.2.2

BlogMapper

这样的映射器类来说,还有一个妙招。它们中间映射的语句可以不需要 在

XML

中来写,而可以使用

Java

注解来替换。比如,上面的

XML

示例可以如下来替换:

package e;public interface BlogMapper { @Select("SELECT * FROM blog WHERE id = #{id}") Blog selectBlog(int id);}对于简单语句来说,使用注解代码会更加清晰,然而

Java

注解对于复杂语句来说就会 混乱,

应该限制使用。 因此,

如果你不得不做复杂的事情,

那么最好使用

XML

来映射语句。

当然这也取决于你和你的项目团队的决定,

看哪种更适合你来使用,

还有以长久方式来 使用映射语句的重要性。也就是说,不要将自己局限在一种方式中。你可以轻松地将注解换 成

XML

映射语句,反之亦然。

范围和生命周期理解我们目前已经讨论过的不同范围和生命周期类是很重要的。 不正确的使用它们会导 致严重的并发问题。

SqlSessionFactoryBuilder这个类可以被实例化,使用和丢弃。一旦你创建了

SqlSessionFactory

后,这个类就不需 要存在了。因此

SqlSessionFactoryBuilder

实例的最佳范围是方法范围

(也就是本地方法变量)。 你可以重用

SqlSessionFactoryBuilder

来创建多个

SqlSessionFactory

实例,

但是最好的方式是 不需要保持它一直存在来保证所有

XML

解析资源,因为还有更重要的事情要做。

SqlSessionFactory一旦被创建,SqlSessionFactory

应该在你的应用执行期间都存在。没有理由来处理或重 新创建它。

使用

SqlSessionFactory

的最佳实践是在应用运行期间不要重复创建多次。 这样的 操作将被视为是非常糟糕的。 因此

SqlSessionFactory

的最佳范围是应用范围。 有很多方法可 以做到,

最简单的就是使用单例模式或者静态单例模式。

SqlSession每个线程都应该有它自己的

SqlSession

实例。SqlSession

的实例不能被共享,也是线程 不安全的。因此最佳的范围是请求或方法范围。绝对不能将

SqlSession

实例的引用放在一个 类的静态字段甚至是实例字段中。 也绝不能将

SqlSession

实例的引用放在任何类型的管理范 围中,

比如

Serlvet

架构中的

HttpSession。 如果你现在正用任意的

Web

框架,

要考虑

SqlSession

放在一个和

HTTP请求对象相似的范围内。换句话说,基于收到的

HTTP

请求,你可以打开 了一个

SqlSession,然后返回响应,就可以关闭它了。关闭

Session

很重要,你应该确保使 用

finally

块来关闭它。下面的示例就是一个确保

SqlSession

关闭的基本模式:

Copyright © 2010-2013 g . All Rights Reserved. 7/79

MyBatis用户指南中文版

version 3.2.2

SqlSession session = ssion();try { // do work} finally { ();}在你的代码中一贯地使用这种模式,

将会保证所有数据库资源都正确地关闭

(假设你没 有通过你自己的连接关闭,这会给

MyBatis

造成一种迹象表明你要自己管理连接资源)

Mapper 实例映射器是你创建绑定映射语句的接口。映射器接口的实例可以从

SqlSession

中获得。那 么从技术上来说,当被请求时,任意映射器实例的最宽范围和

SqlSession

是相同的。然而,

映射器实例的最佳范围是方法范围。也就是说,它们应该在使用它们的方法中被请求,然后 就抛弃掉。它们不需要明确地关闭,那么在请求对象中保留它们也就不是什么问题了,这和

SqlSession

相似。你也许会发现,在这个水平上管理太多的资源的话会失控。保持简单,将 映射器放在方法范围内。下面的示例就展示了这个实践:

SqlSession session = ssion();try { BlogMapper mapper = per(); // do work} finally { ();}重要

Object lifecycle and Dependency Injection Frameworks

Dependency Injection frameworks can create thread safe, transactional

SqlSessions and mappers and inject them directly into your beans so you can justforget about their lifecycle. You may want to have a look at MyBatis-Spring or

MyBatis-Guice sub-projects to know more about using MyBatis with DI frameworks.

XML 映射配置文件MyBatis

XML

配置文件包含了影响

MyBatis

行为甚深的设置和属性信息。

XML

文档 的高层级结构如下:

•configuration

配置

properties

属性

settings

设置

typeAliases

类型命名

Copyright © 2010-2013 g . All Rights Reserved. 8/79

MyBatis用户指南中文版

version 3.2.2

••••

typeHandlers

类型处理器

objectFactory

对象工厂

plugins

插件

environments

环境

•environment

环境变量

•transactionManager

事务管理器

•dataSource

数据源

• databaseIdProvider chinese?

mappers

映射器

properties这些是外部化的,

可替代的属性,

这些属性也可以配置在典型的

Java

属性配置文件中,

或者通过

properties

元素的子元素来传递。例如:

其中的属性就可以在整个配置文件中使用,使用可替换的属性来实现动态配置。比如:

这个例子中的

username

password

将会由

properties

元素中设置的值来替换。

driver

url

属性将会从包含进来的

ties

文件中的值来替换。这里提供很多配置的选项。

属性也可以被传递到

()方法中。例如:

SqlSessionFactory factory = (reader, props);// ... or ...SqlSessionFactory factory = (reader, environment, props);如果在这些地方,属性多于一个的话,MyBatis

按照如下的顺序加载它们:

•在

properties

元素体内指定的属性首先被读取。

•从类路径下资源或

properties

元素的

url

属性中加载的属性第二被读取,它会 覆盖已经存在的完全一样的属性。

•作为方法参数传递的属性最后被读取,

它也会覆盖任一已经存在的完全一样的 属性,这些属性可

Copyright © 2010-2013 g . All Rights Reserved. 9/79

MyBatis用户指南中文版

version 3.2.2

能是从

properties

元素体内和资源/url

属性中加载的。

因此,

最高优先级的属性是那些作为方法参数的,

然后是资源/url

属性,

最后是

properties

元素中指定的属性。

settings这些是极其重要的调整,

它们会修改

MyBatis

在运行时的行为方式。 下面这个表格描述 了设置信息,它们的含义和默认值。

设置参数描述有效值默认值cacheEnabled

这个配置使全局的映射器启用或禁用 缓true | falsetrue

存。

全局启用或禁用延迟加载。当禁用时,

所true | falsetrue

有关联对象都会即时加载。

当启用时,

有延迟加载属性的对象在被

调用时将会完全加载true | falsetrue

任意属性。否则,

每种属性将会按需要加载。

lazyLoadingEnabled

aggressiveLazyLoading

允许或不允许多种结果集从一个单独 的multipleResultSetsEnabled语句中返回(需要适true | falsetrue

合的驱动)

使用列标签代替列名。 不同的驱动在这 方便表现不同。 参考true | falsetrue

驱动文档或充分测

试两种方法来决定所使用的驱动。

允许

JDBC

支持生成的键。 需要适合的

驱动。 如果设置为

true

则这个设置强true | falseFalse

制 生成的键被使用,尽管一些驱动拒绝兼容但仍然有效(比如

useColumnLabel

useGeneratedKeys

Derby)

autoMappingBehavior

指定

MyBatis

如何NONE,

自动映射列到字段/ PARTIAL,

属性。PARTIAL

只FULL

PARTIAL

Copyright © 2010-2013 g . All Rights Reserved. 10/79

MyBatis用户指南中文版

version 3.2.2

设置参数描述会自动映射简单,

没有嵌套的结果。FULL会自动映射任 意复杂的结果(嵌套的或其他情况)

配置默认的执行器。SIMPLE

执行器没

有什么特别之处。SIMPLE REUSEREUSE

执行器重用

SIMPLE

BATCH

预处理语句。BATCH执行器重用语句 和批量更新

设置超时时间,

它决Any positiveNot Set (null)

定驱动等待一个数

integer

据库响应的时间。

有效值默认值defaultExecutorType

defaultStatementTimeout

safeRowBoundsEnabled

Allows using

RowBounds on

nested

statements.

true | falseFalse

Enables

automatic

mapping from

classic databasecolumn names

mapUnderscoreToCamelCase true | falseFalse

A_COLUMN to

camel case

classic Java

property names

aColumn.

localCacheScope MyBatis uses SESSION |

local cache to STATEMENT

prevent circularreferences and

speed up

repeated nested

queries. By

default

(SESSION) all

queries executedduring a sessionare cached. If

SESSION

Copyright © 2010-2013 g . All Rights Reserved. 11/79

MyBatis用户指南中文版

version 3.2.2

设置参数描述有效值默认值localCacheScope=STATEMENT local

session will be

used just for

statement

execution, no

data will be

shared between

two different

calls to the

same ies the

JDBC type for

null values whenno specific JDBCtype was

provided for theparameter. Some

drivers require

specifying the

column JDBC typebut others work

with generic

values like

NULL, VARCHAR orOTHER.

Specifies which

Object's methodstrigger a lazy

load

jdbcTypeForNull

JdbcType

common

OTHER

are: NULL,

VARCHAR and

OTHER

lazyLoadTriggerMethods

A method

name list equals,clone,hashCode,toseparated byString

commas

A type or fully

amicLaqualified

nguageDriver

class name.

Specifies the

language used bydefaultScriptingLanguage default for

dynamic SQL

generation.

callSettersOnNulls

当结果集中含有true | falsefalse

Null值时是否执行映射对象的setter或者Map对象的put方法。此设置对于原始类型如

Copyright © 2010-2013 g . All Rights Reserved. 12/79

MyBatis用户指南中文版

version 3.2.2

设置参数效。

描述有效值默认值int,boolean等无Specifies the

prefix string

that MyBatis Any String Not set

will add to the

logger names.

Specifies which

logging

implementation

MyBatis should

use. If this

setting is not

present logging

implementation

will be

autodiscovered.

SLF4J |

LOG4J |

JDK_LOGGING

|

COMMONS_LOGGNot set

ING |

STDOUT_LOGGING |

NO_LOGGING

logPrefix

logImpl

Specifies the

proxy tool that

MyBatis will useCGLIB |

proxyFactory

for creating JAVASSIST

lazy loading

capable objects.一个设置信息元素的示例,完全的配置如下所示:

CGLIB

Copyright © 2010-2013 g . All Rights Reserved. 13/79

MyBatis用户指南中文版

version 3.2.2

typeAliases类型别名是为

Java

类型命名一个短的名字。 它只和

XML

配置有关,

只用来减少类完全 限定名的多余部分。例如:

使用这个配置, “Blog”可以任意用来替代“. Blog”所使用的地方。

You can also specify a package where MyBatis will search for beans. For example:

Each bean found in , if no annotation is found, will be registered

as an alias using uncapitalized non-qualified class name of the bean. Thas is

will be registered as Author . If the @Alias annotation is

found its value will be used as an alias. See the example below:

@Alias("author")public class Author { ...}对于普通的

Java

类型,有许多内建的类型别名。它们都是大小写不敏感的,由于重载 的名字,要注意原生类型的特殊处理。

别名 映射的类型

_byte

_long

_short

_int

_integer

_double

_float

byte

long

short

int

int

double

float

Copyright © 2010-2013 g . All Rights Reserved. 14/79

MyBatis用户指南中文版

version 3.2.2

别名 映射的类型

_boolean

string

byte

long

short

int

integer

double

float

boolean

date

decimal

object

map

hashmap

list

boolean

String

Byte

Long

Short

Integer

Integer

Double

Float

Boolean

Date

BigDecimal

Object

Map

HashMap

List

bigdecimal BigDecimal

arraylist ArrayList

collection Collection

iterator Iterator

typeHandlers无论是

MyBatis

在预处理语句中设置一个参数,

还是从结果集中取出一个值时,

类型处 理器被用来将获取的值以合适的方式转换成

Java

类型。下面这个表格描述了默认的类型处 理器。

类型处理器

Java

类型

n,

boolean

, byte

, short

r, int

, long

, float

JDBC

类型

任何兼容的布尔值

任何兼容的数字或字节类型

任何兼容的数字或短整型

任何兼容的数字和整型

任何兼容的数字或长整型

任何兼容的数字或单精度浮点型任何兼容的数字或十进制小数类型

BooleanTypeHandler

ByteTypeHandler

ShortTypeHandler

IntegerTypeHandler

LongTypeHandler

FloatTypeHandler

DoubleTypeHandler

BigDecimalTypeHandler

, double

任何兼容的数字或双精度浮点型imal

Copyright © 2010-2013 g . All Rights Reserved. 15/79

MyBatis用户指南中文版

version 3.2.2

类型处理器

Java

类型

byte[]

byte[]

amp

Any

Enumeration Type

JDBC

类型

CHAR

VARCHAR

类型

CLOB

LONGVARCHAR

类型

NVARCHAR

NCHAR

类型

NCLOB

类型

任何兼容的字节流类型

StringTypeHandler

ClobTypeHandler

NStringTypeHandler

NClobTypeHandler

ByteArrayTypeHandler

BlobTypeHandler

DateTypeHandler

DateOnlyTypeHandler

TimeOnlyTypeHandler

SqlTimestampTypeHandler

SqlDateTypeHandler

SqlTimeTypeHandler

ObjectTypeHandler

EnumTypeHandler

BLOB

LONGVARBINARY

类型

TIMESTAMP

类型

DATE

类型

TIME

类型

TIMESTAMP

类型

DATE

类型

TIME

类型

其他或未指定类型

VARCHAR-任何兼容的字符串类型,

作为代码存储(而不是索引)

Any compatible NUMERIC

or DOUBLE, as the

EnumOrdinalTypeHandler Enumeration Type

position is stored (not

the code itself).

你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。

//TODO

translation needed To do so, simply extend the

peHandler class and optionally map your new

TypeHandler class to a JDBC type.

例如:

// @MappedJdbcTypes(R)public class ExampleTypeHandler extends BaseTypeHandler { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType

jdbcType) throws SQLException { ing(i, parameter); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return ing(columnName); } @Override

Copyright © 2010-2013 g . All Rights Reserved. 16/79

MyBatis用户指南中文版

version 3.2.2

public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return ing(columnIndex); } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return ing(columnIndex); }} 使用这样的类型处理器将会覆盖已经存在的处理

Java

String

类型属性和

VARCHAR

参数及结果的类型处理器。 要注意

MyBatis

不会审视数据库元信息来决定使用哪种类型,

所 以你必须在参数和结果映射中指定那是

VARCHAR

类型的字段,来绑定到正确的类型处理 器上。这是因为

MyBatis

直到语句被执行都不知道数据类型的这个现实导致的。

// TODO translation needed MyBatis will know the the Java type that you want to

handle with this TypeHandler by introspecting its generic type, but you can

override this behavior by two means:

•Adding a javaType attribute to the typeHandler element (for example:

javaType="String")

•Adding a @MappedTypes annotation to your TypeHandler class specifying the

list of java types to associate it with. This annotation will be ignored

if the javaType attribute as also been specified.

Associated JDBC type can be specified by two means:•Adding a jdbcType attribute to the typeHandler element (for example:

jdbcType=VARCHAR).

•Adding a @MappedJdbcTypes annotation to your TypeHandler class specifying

the list of JDBC types to associate it with. This annotation will be

ignored if the jdbcType attribute as also been specified.

And finally you can let MyBatis search for your TypeHandlers: Note that when using the autodiscovery feature JDBC types can only be specified

Copyright © 2010-2013 g . All Rights Reserved. 17/79

MyBatis用户指南中文版

version 3.2.2

with annotations.

You can create a generic TypeHandler that is able to handle more than one that purpose add a constructor that receives the class as a parameter and

MyBatis will pass the actual class when constructing the TypeHandler.

//blic class GenericTypeHandler extends BaseTypeHandler { private Class type; public GenericTypeHandler(Class type) { if (type == null) throw new IllegalArgumentException("Type argument cannot be null"); = type; } ...EnumTypeHandler and EnumOrdinalTypeHandler are generic TypeHandlers. We will

learn about them in the following section.

Handling EnumsIf you want to map an Enum, you'll need to use either EnumTypeHandler or

EnumOrdinalTypeHandler.

For example, let's say that we need to store the rounding mode that should be

used with some number if it needs to be rounded. By default, MyBatis uses

EnumTypeHandler to convert the Enum values to their names.

Note EnumTypeHandler is special in the sense that unlike other handlers,

it does not handle just one specific class, but any class that extends

Enum

However, we may not want to store names. Our DBA may insist on an integer code

instead. That's just as easy: add EnumOrdinalTypeHandler to the typeHandlers in

your config file, and now each RoundingMode will be mapped to an integer using

its ordinal value.

javaType="ngMode"/>But what if you want to map the same Enum to a string in one place and to

integer in another?

The auto-mapper will automatically use EnumOrdinalTypeHandler, so if we want to

Copyright © 2010-2013 g . All Rights Reserved. 18/79

MyBatis用户指南中文版

version 3.2.2

go back to using plain old ordinary EnumTypeHandler, we have to tell it, by

explicitly setting the type handler to use for those SQL statements.

(Mapper files aren't covered until the next section, so if this is your first

time reading through the documentation, you may want to skip this for now and

come back to it later.)

insert into users (id, name, funkyNumber, roundingMode) values ( #{id}, #{name}, #{funkyNumber}, #{roundingMode} )

typeHandler="peHandler"/> insert into users2 (id, name, funkyNumber, roundingMode) values ( #{id}, #{name}, #{funkyNumber}, #{roundingMode,

typeHandler=peHandler} )

Copyright © 2010-2013 g . All Rights Reserved. 19/79

MyBatis用户指南中文版

version 3.2.2

Note that this forces us to use a resultMap instead of a resultType in our

select statements.

objectFactoryMyBatis

每次创建结果对象新的实例时,

它使用一个

ObjectFactory

实例来完成。 如果参 数映射存在,默认的

ObjectFactory

不比使用默认构造方法或带参数的构造方法实例化目标 类做的工作多。如果你想重写默认的

ObjectFactory,你可以创建你自己的。比如:

// blic class ExampleObjectFactory extends DefaultObjectFactory { public Object create(Class type) { return (type); } public Object create(Class type, List constructorArgTypes, List

constructorArgs) { return (type, constructorArgTypes, constructorArgs); } public void setProperties(Properties properties) { perties(properties); }} ObjectFactory

接口很简单。它包含两个创建用的方法,一个是处理默认构造方法的,另 外一个是处理带参数构造方法的。最终,setProperties

方法可以被用来配置

ObjectFactory。 在 初 始化 你

ObjectFactory

实例 后

, objectFactory

元素 体 中定 义的 属 性会 被传 递 给

setProperties

方法。

pluginsMyBatis

允许你在某一点拦截已映射语句执行的调用。默认情况下,MyBatis

允许使用 插件来拦截方法调用:

•Executor (update, query, flushStatements, commit, rollback,

getTransaction, close, isClosed)

•ParameterHandler (getParameterObject, setParameters)

•ResultSetHandler (handleResultSets, handleOutputParameters)

•StatementHandler (prepare, parameterize, batch, update, query)

Copyright © 2010-2013 g . All Rights Reserved. 20/79

MyBatis用户指南中文版

version 3.2.2

这些类中方法的详情可以通过查看每个方法的签名来发现

,而且它们的源代码在

MyBatis

的发行包中有。你应该理解你覆盖方法的行为,假设你所做的要比监视调用要多。 如果你尝试修改或覆盖一个给定的方法,

你可能会打破

MyBatis

的核心。 这是低层次的类和 方法,要谨慎使用插件。

使用插件是它们提供的非常简单的力量。 简单实现拦截器接口,

要确定你想拦截的指定 签名。

// @Intercepts({@Signature( type= , method = "update", args = {,})})public class ExamplePlugin implements Interceptor { public Object intercept(Invocation invocation) throws Throwable { return d(); } public Object plugin(Object target) { return (target, this); } public void setProperties(Properties properties) { }} 上面的插件将会拦截在

Executor

实例中所有的“update”方法调用,它也是负责低层次 映射语句执行的内部对象。

NOTE

覆盖配置类

除了用插件来修改

MyBatis

核心行为之外,

你也可以完全覆盖配置类。 简单扩展它,

然后覆盖其中的任意方法,之后传递它到

(myConfig)方法 的调用。这可能会严重影响

MyBatis

的行为,所以要小心。

environmentsMyBatis

可以配置多种环境。这会帮助你将

SQL

映射应用于多种数据库之中。例如,

你也许为开发要设置不同的配置,

测试和生产环境。 或者你可能有多种生产级数据库却共享 相同的模式,所以你会想对不同数据库使用相同的

SQL

映射。这种用例是很多的。

一个很重要的问题要记得:你可以配置多种环境,但你只能为每个

SqlSessionFactory

实例选择一个。

所以,如果你想连接两个数据库,你需要创建两个

SqlSessionFactory

实例,每个数据库 对应一个。而如果是三个数据库,你就需要三个实例,以此类推。记忆起来很简单:

Copyright © 2010-2013 g . All Rights Reserved. 21/79

MyBatis用户指南中文版

version 3.2.2

•每个数据库对应一个

SqlSessionFactory

为了明确创建哪种环境,你可以将它作为可选的参数传递给

SqlSessionFactoryBuilder。 可以接受环境配置的两个方法签名是:

SqlSessionFactory factory = (reader, environment);SqlSessionFactory factory = (reader, environment,properties);如果环境被忽略,那么默认环境将会被加载,如下进行:

SqlSessionFactory factory = (reader);SqlSessionFactory factory = (reader,properties);环境元素定义了如何配置环境。

注意这里的键:

••••默认的环境

ID(比如:default=”development”)。

每个

environment

元素定义的环境

ID(比如:id=”development”)。

事务管理器的配置(比如:type=”JDBC”)。

数据源的配置(比如:type=”POOLED”)。

默认的环境和环境

ID

是自我解释的。你可以使用你喜欢的名称来命名,只要确定默认 的要匹配其中之一。

transactionManager

MyBatis

中有两种事务管理器类型(也就是

type=”[JDBC|MANAGED]”):

•JDBC –

这个配置直接简单使用了

JDBC

的提交和回滚设置。 它依赖于从数据源得 到的连接来管理事务范围。

•MANAGED –

这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让 容器来管理事务的整个生命周期(比如

Spring

JEE

应用服务器的上下文)

默认 情况下它会关闭连接。

然而一些容器并不希望这样,

因此如果你需要从连接中停止 它,将

closeConnection

属性设置为

false。例如:

Copyright © 2010-2013 g . All Rights Reserved. 22/79

MyBatis用户指南中文版

version 3.2.2

NOTE If you are planning to use MyBatis with Spring there is no need to

configure any TransactionManager because the Spring module will set its own one

overriding any previously set configuration.

这两种事务管理器都不需要任何属性。然而它们都是类型别名,要替换使用它们,你需 要放置将你自己的类的完全限定名或类型别名,它们引用了你对

TransactionFactory

接口的实现 类。

public interface TransactionFactory { void setProperties(Properties props);

Transaction newTransaction(Connection conn); Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean

autoCommit);

}任何在

XML

中配置的属性在实例化之后将会被传递给

setProperties()方法。 你的实现类 需要创建一个事务接口的实现,这个接口也很简单:

public interface Transaction { Connection getConnection() throws SQLException; void commit() throws SQLException; void rollback() throws SQLException; void close() throws SQLException;}使用这两个接口,你可以完全自定义

MyBatis

对事务的处理。

dataSource

dataSource

元素使用基本的

JDBC

数据源接口来配置

JDBC

连接对象的资源。

•许多

MyBatis

的应用程序将会按示例中的例子来配置数据源。 然而它并不是必须的。 要知道为了方便使用延迟加载,数据源才是必须的。

有三种内建的数据源类型(也就是

type=”???”):

UNPOOLED –

这个数据源的实现是每次被请求时简单打开和关闭连接。它有一点慢,

这是对简单应用程序的一个很好的选择,

因为它不需要及时的可用连接。 不同的数据库对这 个的表现也是不一样的,

所以对某些数据库来说配置数据源并不重要,

这个配置也是闲置的。

UNPOOLED

类型的数据源仅仅用来配置以下

5

种属性:

•driver –

这是

JDBC

驱动的

Java

类的完全限定名(如果你的驱动包含,它也不是 数据源类)。

•url –

这是数据库的

JDBC URL

地址。

•username –

登录数据库的用户名。

•password –

登录数据库的密码。

Copyright © 2010-2013 g . All Rights Reserved. 23/79

MyBatis用户指南中文版

version 3.2.2

•defaultTransactionIsolationLevel –

默认的连接事务隔离级别。

作为可选项,你可以传递数据库驱动的属性。要这样做,属性的前缀是以“driver.”开 头的,例如:

•ng=UTF8

这 样 就 会 传 递 以 值 “

UTF8 ”

来 传 递 属 性 “

encoding ”,

它 是 通 过

nection(url,driverProperties)方法传递给数据库驱动。

POOLED –

这是

JDBC

连接对象的数据源连接池的实现,用来避免创建新的连接实例 时必要的初始连接和认证时间。这是一种当前

Web

应用程序用来快速响应请求很流行的方 法。

除了上述(UNPOOLED)的属性之外,还有很多属性可以用来配置

POOLED

数据源:

•poolMaximumActiveConnections –

在任意时间存在的活动(也就是正在使用)连 接的数量。默认值:10

•poolMaximumIdleConnections –

任意时间存在的空闲连接数。

•poolMaximumCheckoutTime –

在被强制返回之前,池中连接被检查的时间。默认 值:20000

毫秒(也就是

20

秒)

•poolTimeToWait –

这是给连接池一个打印日志状态机会的低层次设置,还有重新 尝试获得连接,

这些情况下往往需要很长时间 为了避免连接池没有配置时静默失 败)。默认值:20000

毫秒(也就是

20

秒)

•poolPingQuery –

发送到数据的侦测查询,用来验证连接是否正常工作,并且准备 接受请求。默认是“NO PING QUERY SET” ,这会引起许多数据库驱动连接由一 个错误信息而导致失败。•poolPingEnabled –

这是开启或禁用侦测查询。如果开启,你必须用一个合法的

SQL

语句(最好是很快速的)设置

poolPingQuery

属性。默认值:false。

•poolPingConnectionsNotUsedFor –

这是用来配置

poolPingQuery

多次时间被用一次。这可以被设置匹配标准的数据库连接超时时间,

来避免不必要的侦测。 默认值: 0(也就是所有连接每一时刻都被侦测-但仅仅当

poolPingEnabled

true

时适用)。

JNDI –

这个数据源的实现是为了使用如

Spring

或应用服务器这类的容器,

容器可以集 中或在外部配置数据源,然后放置一个

JNDI

上下文的引用。这个数据源配置只需要两个属 性:

•initial_context –

这 个 属 性 用 来 从 初 始 上 下 文 中 寻 找 环 境

(

也 就 是

(initial——context)

。这是个可选属性,如果被忽略,那么

data_source

属性将会直接以

initialContext

为背景再次寻找。

•data_source –

这是引用数据源实例位置的上下文的路径。它会以由

initial_context

查询返回的环境为背景来查找,如果

initial_context

没有返回结果时,直接以初始 上下文为环境来查找。

和其他数据源配置相似,

它也可以通过名为 “env.”

的前缀直接向初始上下文发送属性。 比如:

•ng=UTF8

在初始化之后,这就会以值“UTF8”向初始上下文的构造方法传递名为“encoding”

的属性。

databaseIdProviderMyBatis is able to execute different statements depending on your database

Copyright © 2010-2013 g . All Rights Reserved. 24/79

MyBatis用户指南中文版

version 3.2.2

vendor. The multi-db vendor support is based on the mapped statements databaseIdattribute. MyBatis will load all statements with no databaseId attribute or witha databaseId that matches the current one. If case the same statement if found

with and without the databaseId the latter will be discarded. To enable the

multi vendor support add a databaseIdProvider to file as

follows:

The VENDOR implementation databaseIdProvider sets as a databaseId the String

returned by DatabaseMetaData#getDatabaseProductName(). As usually that string istoo long and also, different versions of the same product return different

values, so you may want to translate it to a shorter one by adding properties

like follows:

When properties are provided, the VENDOR databaseIdProvider will search the

property value corresponding to the first key found in the returned database

product name or "null" if there is not a matching property. In this case, if

getDatabaseProductName() returns "Oracle (DataDirect)" the databaseId will be

set to "oracle".

You can build your own database provider by implementing the interface

seIdProvider and registerin it in

:

public interface DatabaseIdProvider { void setProperties(Properties p);

String getDatabaseId(DataSource dataSource) throws SQLException;}mappers既然

MyBatis

的行为已经由上述元素配置完了,我们现在就要定义

SQL

映射语句了。 但是,

首先我们需要告诉

MyBatis

到哪里去找到这些语句。

Java

在这方面没有提供一个很好 的方法,

所以最佳的方式是告诉

MyBatis

到哪里去找映射文件。 你可以使用相对于类路径的 资源引用,或者字符表示,或

url

引用的完全限定名(包括

file:///URLs)

。例如:

Copyright © 2010-2013 g . All Rights Reserved. 25/79

MyBatis用户指南中文版

version 3.2.2

这些语句简单告诉了

MyBatis

去哪里找映射文件。其余的细节就是在每个

SQL

映射文 件中了,下面的部分我们来讨论

SQL

映射文件。

Mapper XML 文件MyBatis

真正的力量是在映射语句中。这里是奇迹发生的地方。对于所有的力量,SQL

映射的

XML

文件是相当的简单。当然如果你将它们和对等功能的

JDBC

代码来比较,你会 发现映射文件节省了大约

95%的代码量。MyBatis

的构建就是聚焦于

SQL

的,使其远离于 普通的方式。

SQL

映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):

•cache –

配置给定命名空间的缓存。

•cache-ref –

从其他命名空间引用缓存配置。

•resultMap –

最复杂,也是最有力量的元素,用来描述如何从数据库结果集中来加 载你的对象。

•parameterMap –

已经被废弃了!老式风格的参数映射。内联参数是首选,这个元 素可能在将•••••来被移除。这里不会记录。

sql –

可以重用的

SQL

块,也可以被其他语句引用。

insert –

映射插入语句

update –

映射更新语句

delete –

映射删除语句

select –

映射查询语句

Copyright © 2010-2013 g . All Rights Reserved. 26/79

MyBatis用户指南中文版

version 3.2.2

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

select查询语句是使用

MyBatis

时最常用的元素之一。 直到你从数据库取出数据时才会发现将 数据存在数据库中是多么的有价值,

所以许多应用程序查询要比更改数据多的多。 对于每次 插入,更新或删除,那也会有很多的查询。这是

MyBatis

的一个基本原则,也是将重心和努 力放到查询和结果映射的原因。对简单类别的查询元素是非常简单的。比如:

这个语句被称作

selectPerson,

使用一个

int (或

Integer)

类型的参数,

并返回一个

HashMap

类型的对象,其中的键是列名,值是列对应的值。

注意参数注释:

#{id}这就告诉

MyBatis

创建一个预处理语句参数。 使用

JDBC,

这样的一个参数在

SQL

中会 由一个“?”来标识,并被传递到一个新的预处理语句中,就像这样:

// Similar JDBC code, NOT MyBatis…String selectPerson = "SELECT * FROM PERSON WHERE ID=?";PreparedStatement ps = eStatement(selectPerson);(1,id);当然,

这需要很多单独的

JDBC

的代码来提取结果并将它们映射到对象实例中,

这就是

MyBatis

节省你时间的地方。我们需要深入了解参数和结果映射。那些细节部分我们下面来 了解。

select

元素有很多属性允许你配置,来决定每条语句的作用细节。

select from some_table where id = #{id}

Copyright © 2010-2013 g . All Rights Reserved. 31/79

MyBatis用户指南中文版

version 3.2.2

Parameters在之前的语句中,

你已经看到了一些简单参数的示例。

MyBatis

中参数是非常强大的 在 元素。对于简单的做法,大概

90%的情况,是不用太多的,比如:

上面的这个示例说明了一个非常简单的命名参数映射。参数类型被设置为“int” ,因此 这个参数可以被设置成任何内容。 原生的类型或简单数据类型,

比如整型和没有相关属性的 字符串,因此它会完全用参数来替代。然而,如果你传递了一个复杂的对象,那么

MyBatis

的处理方式就会有一点不同。比如:

insert into users (id, username, password) values (#{id}, #{username}, #{password})如果

User

类型的参数对象传递到了语句中, username

password

属性将会被查找, id、 然后它们的值就被传递到预处理语句的参数中。

这点对于传递参数到语句中非常好。但是对于参数映射也有一些其他的特性。

首先,像

MyBatis

的其他部分,参数可以指定一个确定的数据类型。

#{property,javaType=int,jdbcType=NUMERIC}像

MyBatis

的剩余部分,javaType

通常可以从参数对象中来去顶,除非对象是一个

HashMap。那么

javaType

应该被确定来保证使用正确类型处理器。

注意 如果

null

被当作值来传递,对于所有可能为空的列,JDBC Type

是需要的。以可 以自己通过阅读预处理语句的

setNull()方法的

JavaDocs

文档来研究这个。

为了自定义类型处理器,你可以指定一个确定的类型处理器类(或别名),

比如:

#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}尽管它看起来繁琐,但是实际上是你很少设置它们其中之一。

对于数值类型,对于决定有多少数字是相关的,有一个数值范围。

#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}

Copyright © 2010-2013 g . All Rights Reserved. 32/79

MyBatis用户指南中文版

version 3.2.2

最后,mode

属性允许你指定

IN,OUT

INOUT

参数。如果参数为

OUT

INOUT,

参数对象属性的真实值将会被改变,就像你期望你需要你个输出参数。如果

mode

OUT (或

INOUT) ,而且

jdbcType

CURSOR(也就是

Oracle

REFCURSOR) ,你必须指定 一个

resultMap

来映射结果集到参数类型。要注意这里的

javaType

属性是可选的,如果左边 的空白是

jdbcType

CURSOR

类型,它会自动地被设置为结果集。

#{department, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=departmentResultMap}MyBatis

也支持很多高级的数据类型,比如结构体,但是当注册

out

参数时你必须告诉 语句类型名称。比如(再次提示,在实际中不要像这样换行):

#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}尽管所有这些强大的选项很多时候你只简单指定属性名,MyBatis

会自己计算剩余的。 最多的情况是你为

jdbcType

指定可能为空的列名。

#{firstName}#{middleInitial,jdbcType=VARCHAR}#{lastName}字符串替换

默认情况下,使用#{}格式的语法会导致

MyBatis

创建预处理语句属性并以它为背景设 置安全的值(比如?)

。这样做很安全,很迅速也是首选做法,有时你只是想直接在

SQL

语 句中插入一个不改变的字符串。比如,像

ORDER BY,你可以这样来使用:

ORDER BY ${columnName}这里

MyBatis

不会修改或转义字符串。

重要 接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会 导致潜在的

SQL

注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检 查。

Result MapsresultMap

元素是

MyBatis

中最重要最强大的元素。它就是让你远离

90%的需要从结果 集中取出数据的

JDBC

代码的那个东西,

而且在一些情形下允许你做一些

JDBC

不支持的事 情。 事实上,

编写相似于对复杂语句联合映射这些等同的代码,

也许可以跨过上千行的代码。

ResultMap

的设计就是简单语句不需要明确的结果映射,而很多复杂语句确实需要描述它们 的关系。

Copyright © 2010-2013 g . All Rights Reserved. 33/79

MyBatis用户指南中文版

version 3.2.2

你已经看到简单映射语句的示例了,但没有明确的

resultMap。比如:

这样一个语句简单作用于所有列被自动映射到

HashMap

的键上,这由

resultType

属性 指定。这在很多情况下是有用的,但是

HashMap

不能很好描述一个领域模型。那样你的应 用程序将会使用

JavaBeans

POJOs(Plain Old Java Objects,普通

Java

对象)来作为领域 模型。MyBatis

对两者都支持。看看下面这个

JavaBean:

package ;public class User { private int id; private String username; private String hashedPassword;

public int getId() { return id; } public void setId(int id) { = id; } public String getUsername() { return username; } public void setUsername(String username) { me = username; } public String getHashedPassword() { return hashedPassword; } public void setHashedPassword(String hashedPassword) { Password = hashedPassword; }}基于

JavaBean

的规范,上面这个类有

3

个属性:id,username

hashedPassword。这些 在

select

语句中会精确匹配到列名。

这样的一个

JavaBean

可以被映射到结果集,就像映射到

HashMap

一样简单。

要记住类型别名是你的伙伴。使用它们你可以不用输入类的全路径。比如:

这些情况下,MyBatis

会在幕后自动创建一个

ResultMap,基于属性名来映射列到

JavaBean

的属性上。如果列名没有精确匹配,你可以在列名上使用

select

字句的别名(一个 基本的

SQL

特性)来匹配标签。比如:

ResultMap

最优秀的地方你已经了解了很多了,但是你还没有真正的看到一个。这些简 单的示例不需要比你看到的更多东西。 只是出于示例的原因,

让我们来看看最后一个示例中 外部的

resultMap

是什么样子的,这也是解决列名不匹配的另外一种方式。

引用它的语句使用

resultMap

属性就行了(注意我们去掉了

resultType

属性)。比如:

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

Copyright © 2010-2013 g . All Rights Reserved. 35/79

MyBatis用户指南中文版

version 3.2.2

高级结果映射MyBatis

创建的一个想法:数据库不用永远是你想要的或需要它们是什么样的。而我们 最喜欢的数据库最好是第三范式或

BCNF

模式,但它们有时不是。如果可能有一个单独的 数据库映射,所有应用程序都可以使用它,这是非常好的,但有时也不是。结果映射就是

MyBatis

提供处理这个问题的答案。

比如,我们如何映射下面这个语句?

你可能想把它映射到一个智能的对象模型,包含一个作者写的博客,有很多的博文,每 篇博文有零条或多条的评论和标签。 下面是一个完整的复杂结果映射例子

(假设作者,

博客,

博文,

评论和标签都是类型的别名)

我们来看看,

。 但是不用紧张,

我们会一步一步来说明。 当天最初它看起来令人生畏,但实际上非常简单。

Copyright © 2010-2013 g . All Rights Reserved. 36/79

MyBatis用户指南中文版

version 3.2.2

resultMap

元素有很多子元素和一个值得讨论的结构。 下面是

resultMap

元素的概念视图

resultMap•constructor -

类在实例化时,用来注入结果到构造方法中

•idArg - ID

参数;标记结果作为

ID

可以帮助提高整体效能

•arg -

注入到构造方法的一个普通结果

•id –

一个

ID

结果;标记结果作为

ID

可以帮助提高整体效能

•result –

注入到字段或

JavaBean

属性的普通结果

•association –

一个复杂的类型关联;许多结果将包成这种类型

•嵌入结果映射 – 结果映射自身的关联,或者参考一个

•collection –

复杂类型的集

•嵌入结果映射 – 结果映射自身的集,或者参考一个

•discriminator –

使用结果值来决定使用哪个结果映射

•case –

基于某些值的结果映射

•嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相 同的元素,或者它可以参照一个外部的结果映射。

ResultMap Attributes

Copyright © 2010-2013 g . All Rights Reserved. 37/79

MyBatis用户指南中文版

version 3.2.2

AttributeidtypeautoMappingDescriptionA unique identifier in this namespace that can be used to

reference this result map.A fully qualified Java class name, or a type alias (see the tableabove for the list of built-in type aliases).

If present, MyBatis will enable or disable the automapping for

this ResultMap. This attribute overrides the global

autoMappingBehavior. Default: unset.

最佳实践 通常逐步建立结果映射。单元测试的真正帮助在这里。如果你尝试创建 一次创建一个向上面示例那样的巨大的结果映射,

那么可能会有错误而且很难去控制它 来工作。开始简单一些,一步一步的发展。而且要进行单元测试!使用该框架的缺点是 它们有时是黑盒(是否可见源代码)

。你确定你实现想要的行为的最好选择是编写单元 测试。它也可以你帮助得到提交时的错误。

下面一部分将详细说明每个元素。

id & result这些是结果映射最基本内容。id

result

都映射一个单独列的值到简单数据类型(字符 串,整型,双精度浮点数,日期等)的单独属性或字段。

这两者之间的唯一不同是

id

表示的结果将是当比较对象实例时用到的标识属性。这帮 助来改进整体表现,特别是缓存和嵌入结果映射(也就是联合映射)

每个都有一些属性:

Id and Result Attributes属性描述映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同 的

JavaBeans

的属性,那么就会使用。否则

MyBatis

将会寻找给定名称

property

的字段。这两种情形你可以使用通常点式的复杂属性导航。比如,你 可以这样映射一些东西:

“username” ,或者映射到一些复杂的东西: “”

从数据库中得到的列名,或者是列名的重命名标签。这也是通常和会 传递给

ing(columnName)方法参数中相同的字符串。

一个

Java

类的完全限定名,或一个类型别名(参加上面内建类型别名 的列表)

。如果你映射到一个

JavaBean,MyBatis

通常可以断定类型。 然而,如果你映射到的是HashMap,那么你应该明确地指定

javaType

来保证所需的行为。

在这个表格之后的所支持的

JDBC

类型列表中的类型。JDBC

类型是仅 仅需要对插入,更新和删除操作可能为空的列进行处理。这是

JDBC jdbcType

的需要,而不是

MyBatis

的。如果你直接使用

JDBC

编程,你需要指定 这个类型-但仅仅对可能为空的值。

我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默 认的类型处理器。propertycolumnjavaTypejdbcTypetypeHandler

Copyright © 2010-2013 g . All Rights Reserved. 38/79

MyBatis用户指南中文版

version 3.2.2

属性描述这个属性值是类的完全限定名或者是一个类型处理 器的实现,或者是类型别名。

支持的 JDBC 类型为了未来的参考,MyBatis

通过包含的

jdbcType

枚举型,支持下面的

JDBC

类型。

BITTINYINTSMALLINTINTEGERBIGINT构造方法FLOATREALDOUBLENUMERICDECIMALCHARVARCHARLONGVARCHARDATETIMETIMESTAMPBINARYVARBINARYLONGVARBINARYNULLOTHERBLOGCLOBBOOLEANCURSORUNDEFINEDNVARCHARNCHARNCLOBARRAY 对于大多数数据传输对象(Data Transfer Object,DTO)类型,属性可以起作用,而且像 你绝大多数的领域模型,

指令也许是你想使用一成不变的类的地方。 通常包含引用或查询数 据的表很少或基本不变的话对一成不变的类来说是合适的。 构造方法注入允许你在初始化时 为类设置属性的值,而不用暴露出公有方法。MyBatis

也支持私有属性和私有

JavaBeans

属 性来达到这个目的,但是一些人更青睐构造方法注入。构造方法元素支持这个。

看看下面这个构造方法:

public class User { //... public User(int id, String username) { //... }//...}为了向这个构造方法中注入结果,MyBatis

需要通过它的参数的类型来标识构造方法。

Java

没有自查(反射)参数名的方法。所以当创建一个构造方法元素时,保证参数是按顺序 排列的,而且数据类型也是确定的。

剩余的属性和规则和固定的

id

result

元素是相同的。

Copyright © 2010-2013 g . All Rights Reserved. 39/79

MyBatis用户指南中文版

version 3.2.2

属性描述来自数据库的类名,或重命名的列标签。这和通常传递给

ing(columnName)方法的字符串是相同的。

一个

Java

类的完全限定名,或一个类型别名(参加上面内建类型别名的列表)。 如果你映射到一个

JavaBean,MyBatis

通常可以断定类型。然而,如 果你映射到的是HashMap,那么你应该明确地指定

javaType

来保证所需的 行为。

在这个表格之前的所支持的

JDBC

类型列表中的类型。JDBC

类型是仅仅 需要对插入,

更新和删除操作可能为空的列进行处理。这是

JDBC

的需要, jdbcType

而不是

MyBatis

的。如果你直接使用

JDBC

编程,你需要指定这个类型-但 仅仅对可能为空的值。

我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的 类型处理器。 这个属性值是类的完全限定名或者是一个类型处理器的实现,

或者是类型别名。

columnjavaTypejdbcTypetypeHandlerselectThe ID of another mapped statement that will load the complex

type required by this property mapping. The values retrieved fromcolumns specified in the column attribute will be passed to the

target select statement as parameters. See the Association

element for more.

This is the ID of a ResultMap that can map the nested results of

this argument into an appropriate object graph. This is an

alternative to using a call to another select statement. It

allows you to join multiple tables together into a single

ResultSet. Such a ResultSet will contain duplicated, repeating

groups of data that needs to be decomposed and mapped properly toa nested object graph. To facilitate this, MyBatis lets you

"chain" result maps together, to deal with the nested results.

See the Association element below for more.

resultMap关联 关联元素处理“有一个”类型的关系。比如,在我们的示例中,一个博客有一个用户。 关联映射就工作于这种结果之上。你指定了目标属性,来获取值的列,属性的

java

类型(很 多情况下

MyBatis

可以自己算出来) ,如果需要的话还有

jdbc

类型,如果你想覆盖或获取的 结果值还需要类型控制器。

关联中不同的是你需要告诉

MyBatis

如何加载关联。MyBatis

在这方面会有两种不同的 方式:

•嵌套查询:通过执行另外一个

SQL

映射语句来返回预期的复杂类型。

•嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。首先,然让我们来查看这个元素的属性。所有的你都会看到,它和普通的只由

select

Copyright © 2010-2013 g . All Rights Reserved. 40/79

MyBatis用户指南中文版

version 3.2.2

resultMap

属性的结果映射不同。

属性描述映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同的

property

JavaBeans

的属性,

那么就会使用。 否则

MyBatis

将会寻找给定名称的字段。

这两种情形你可以使用通常点式的复杂属性导航。比如,你可以这样映射 一 些 东

西

:“ username ”,

或 者 映 射 到 一 些 复 杂 的 东 西

:

“”

一个

Java

类的完全限定名,或一个类型别名(参加上面内建类型别名的列 表)

。如果你映射到一个

JavaBean,MyBatis

通常可以断定类型。然而,如

javaType

果你映射到的是

HashMap,那么你应该明确地指定

javaType

来保证所需的 行为。

在这个表格之前的所支持的

JDBC

类型列表中的类型。JDBC

类型是仅仅 需要对插入,

更新和删除操作可能为空的列进行处理。这是

JDBC

的需要, jdbcType

而不是

MyBatis

的。如果你直接使用

JDBC

编程,你需要指定这个类型-但 仅仅对可能为空的值。

我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的

typeHandler

类型处理器。 这个属性值是类的完全限定名或者是一个类型处理器的实现,

或者是类型别名。

propertyjavaTypejdbcTypetypeHandler关联的嵌套查询属性描述来自数据库的类名,或重命名的列标签。这和通常传递给

ing(columnName)方法的字符串是相同的。

column

注 意

:

要 处

理 复 合 主 键

,

你 可 以 指 定 多 个 列 名 通 过

column= ”

{prop1=col1,prop2=col2} ”

这种语法来传递给嵌套查询语 句。这会引起

prop1

prop2

以参数对象形式来设置给目标嵌套查询语句。

另外一个映射语句的

ID,可以加载这个属性映射需要的复杂类型。获取的 在列属性中指定的列的值将被传递给目标

select

语句作为参数。表格后面 有一个详细的示例。

select

注意

:

要 处 理 复 合 主 键

,

你 可 以 指 定 多 个 列 名 通 过

column= ”

{prop1=col1,prop2=col2} ”

这种语法来传递给嵌套查询语 句。这会引起

prop1

prop2

以参数对象形式来设置给目标嵌套查询语句。

columnselect示例:

select="selectAuthor"/>我们有两个查询语句:一个来加载博客,另外一个来加载作者,而且博客的结果映射描 述了“selectAuthor”语句应该被用来加载它的

author

属性。

其他所有的属性将会被自动加载,假设它们的列和属性名相匹配。

这种方式很简单,

但是对于大型数据集合和列表将不会表现很好。 问题就是我们熟知的 “N+1

查询问题”。概括地讲,N+1

查询问题可以是这样引起的:

•你执行了一个单独的

SQL

语句来获取结果列表(就是“+1”)。

•对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。

这个问题会导致成百上千的

SQL

语句被执行。这通常不是期望的。

MyBatis

能延迟加载这样的查询就是一个好处,因此你可以分散这些语句同时运行的消 耗。然而,如果你加载一个列表,之后迅速迭代来访问嵌套的数据,你会调用所有的延迟加 载,这样的行为可能是很糟糕的。

所以还有另外一种方法。

关联的嵌套结果属性描述这是结果映射的

ID,可以映射关联的嵌套结果到一个合适的对象图中。这 是一种替代方法来调用另外一个查询语句。这允许你联合多个表来合成到

resultMap

一个单独的结果集。这样的结果集可能包含重复,数据的重复组需要被分 解,合理映射到一个嵌套的对象图。为了使它变得容易,MyBatis

让你“链 接”结果映射,来处理嵌套结果。一个例子会很容易来仿照,这个表格后 面也有一个示例。

resultMapcolumnPrefixWhen joining multiple tables, you would have to use column

alias to avoid duplicated column names in the ResultSet.

Specifying columnPrefix allows you to map such columns to an

external resultMap. Please see the example explained later in

this section.

By default a child object is created only if at least one of

the columns mapped to the child's properties is non null. With

this attribute you can change this behaviour by specifiying

which columns must have a value so MyBatis will create a child

object only if any of those columns is not null. Multiple

column names can be specified using a comma as a separator.

Default value: unset.

notNullColumn在上面你已经看到了一个非常复杂的嵌套关联的示例。 下面这个是一个非常简单的示例 来说明它如何工作。代替了执行一个分离的语句,我们联合博客表和作者表在一起,就像:

注意这个联合查询,

以及采取保护来确保所有结果被唯一而且清晰的名字来重命名。 这使得映射非常简单。现在我们可以映射这个结果:

resultMap="authorResult"/> 在上面的示例中你可以看到博客的作者关联代表着“authorResult”结果映射来加载作 者实例。

非常重要:

在嵌套据诶过映射中

id

元素扮演了非常重要的角色。应应该通常指定一个 或多个属性,它们可以用来唯一标识结果。实际上就是如果你离开她了,但是有一个严重的 性能问题时

MyBatis

仍然可以工作。选择的属性越少越好,它们可以唯一地标识结果。主键 就是一个显而易见的选择(尽管是联合主键)。

现在,上面的示例用了外部的结果映射元素来映射关联。这使得

Author

结果映射可以 重用。然而,如果你不需要重用它的话,或者你仅仅引用你所有的结果映射合到一个单独描 述的结果映射中。你可以嵌套结果映射。这里给出使用这种方式的相同示例:

Copyright © 2010-2013 g . All Rights Reserved. 43/79

MyBatis用户指南中文版

version 3.2.2

What if the blog has a co-author? The select statement would look like:

Recall that the resultMap for Author is defined as follows.

Because the column names in the results differ from the columns defined in the

resultMap, you need to specify columnPrefix to reuse the resultMap for mapping

co-author results.

Copyright © 2010-2013 g . All Rights Reserved. 44/79

MyBatis用户指南中文版

version 3.2.2

上面你已经看到了如何处理“有一个”类型关联。但是“有很多个”是怎样的?下面这 个部分就是来讨论这个主题的。

集合 集合元素的作用几乎和关联是相同的。实际上,它们也很相似,文档的异同是多余的。 所以我们更多关注于它们的不同。

我们来继续上面的示例,一个博客只有一个作者。但是博客有很多文章。在博客类中,

这可以由下面这样的写法来表示:

private List posts;要映射嵌套结果集合到

List

中,我们使用集合元素。就像关联元素一样,我们可以从 连接中使用嵌套查询,或者嵌套结果。

集合的嵌套查询首先,让我们看看使用嵌套查询来为博客加载文章。

select="selectPostsForBlog"/>这里你应该注意很多东西,但大部分代码和上面的关联元素是非常相似的。首先,你应 该注意我们使用的是集合元素。然后要注意那个新的“ofType”属性。这个属性用来区分

JavaBean(或字段)属性类型和集合包含的类型来说是很重要的。所以你可以读出下面这个 映射:

Copyright © 2010-2013 g . All Rights Reserved. 45/79

MyBatis用户指南中文版

version 3.2.2

select="selectPostsForBlog"/>读作: “在

Post

类型的

ArrayList

中的

posts

的集合。”

javaType

属性是不需要的,因为

MyBatis

在很多情况下会为你算出来。所以你可以缩短 写法:

集合的嵌套结果至此,你可以猜测集合的嵌套结果是如何来工作的,因为它和关联完全相同,除了它应 用了一个“ofType”属性

First, let's look at the SQL:我们又一次联合了博客表和文章表,而且关注于保证特性,结果列标签的简单映射。现 在用文章映射集合映射博客,可以简单写为:

同样,要记得

id

元素的重要性,如果你不记得了,请阅读上面的关联部分。

同样,

如果你引用更长的形式允许你的结果映射的更多重用,

你可以使用下面这个替代 的映射:

Copyright © 2010-2013 g . All Rights Reserved. 46/79

MyBatis用户指南中文版

version 3.2.2

注意 这个对你所映射的内容没有深度,广度或关联和集合相联合的限制。当映射它们 时你应该在大脑中保留它们的表现。 你的应用在找到最佳方法前要一直进行的单元测试和性 能测试。好在

myBatis

让你后来可以改变想法,而不对你的代码造成很小(或任何)影响。

高级关联和集合映射是一个深度的主题。文档只能给你介绍到这了。加上一点联系,你 会很快清楚它们的用法。

鉴别器 有时一个单独的数据库查询也许返回很多不同

(但是希望有些关联)

数据类型的结果集。 鉴别器元素就是被设计来处理这个情况的,

还有包括类的继承层次结构。 鉴别器非常容易理 解,因为它的表现很像

Java

语言中的

switch

语句。

定义鉴别器指定了

column

javaType

属性。 列是

MyBatis

查找比较值的地方。

JavaType

是需要被用来保证等价测试的合适类型(尽管字符串在很多情形下都会有用)。比如:

在这个示例中, MyBatis

会从结果集中得到每条记录,

然后比较它的

vehicle

类型的值。 如果它匹配任何一个鉴别器的实例,那么就使用这个实例指定的结果映射。换句话说,这样 做完全是剩余的结果映

Copyright © 2010-2013 g . All Rights Reserved. 47/79

MyBatis用户指南中文版

version 3.2.2

射被忽略(除非它被扩展,这在第二个示例中讨论)

。如果没有任何 一个实例相匹配,那么

MyBatis

仅仅使用鉴别器块外定义的结果映射。所以,如果

carResult

按如下声明:

那么只有

doorCount

属性会被加载。这步完成后完整地允许鉴别器实例的独立组,尽管 和父结果映射可能没有什么关系。这种情况下,我们当然知道

cars

vehicles

之间有关系,

Car

是一个

Vehicle

实例。因此,我们想要剩余的属性也被加载。我们设置的结果映射的 简单改变如下。

现在

vehicleResult

carResult

的属性都会被加载了。

尽管曾经有些人会发现这个外部映射定义会多少有一些令人厌烦之处。 因此还有另外一 种语法来做简洁的映射风格。比如:

要记得 这些都是结果映射,

如果你不指定任何结果,

那么

MyBatis

将会为你自动匹配列 和属性。所以这些例子中的大部分是很冗长的,而其实是不需要的。也就是说,很多数据库 是很复杂的,我们不太可能对所有示例都能依靠它。

Copyright © 2010-2013 g . All Rights Reserved. 48/79

MyBatis用户指南中文版

version 3.2.2

Auto-mappingAs you have already seen in the previous sections, in simple cases MyBatis can

auto-map the results for you and in others you will need to build a result map.

But as you will see in this section you can also mix both strategies. Let's havea deeper look at how auto-mapping works.

When auto-mapping results MyBatis will get the column name and look for a

property with the same name ignoring case. That means that if a column named

ID

and property named

id are found, MyBatis will set the

id property with the

ID

column value.

Usually database columns are named using uppercase letters and underscores

between words and java properties often follow the camelcase naming covention.

To enable the auto-mapping between them set the setting mapUnderscoreToCamelCaseto true.

Auto-mapping works even when there is an specific result map. When this happens,for each result map, all columns that are present in the ResultSet that have nota manual mapping will be auto-mapped, then manual mappings will be processed. Inthe following sample

id and

userName columns will be auto-mapped and

hashed_password column will be mapped. There are three auto-mapping levels:

•NONE - disables auto-mapping. Only manually mapped properties will be set.•PARTIAL - will auto-map results except those that have nested result

mappings defined inside (joins).

•FULL - auto-maps everything.

The default value is PARTIAL, and it is so for a reason. When FULL is used

auto-mapping will be performed when processing join results and joins retrieve

data of several different entities in the same row hence this may result in

undesired mappings. To understand the risk have a look at the following sample:

Copyright © 2010-2013 g . All Rights Reserved. 49/79


本文标签: 映射 结果 类型 语句

更多相关文章

OI题目类型总结整理

9月前

## 本蒟蒻的小整理qwq~~持续更新(咕咕咕) 数据结构 数据结构 知识点梳理 数据结构——线段树 推荐yyb dalao的总结——戳我 以后维护线段

软件开发中的非功能需求类型

9月前

在软件开发中,很多程序员都将完成需求当作任务目标。但是在验收、代码评审的时候,我们对于程序员来讲,除了能完成外,还有一些其它一些要求条件&#xf

MT675232平台 KK和L版本支持的虚拟sensor类型有哪些

8月前

[DESCRIPTION] MT675232平台 KK和L版本支持的虚拟sensor类型有哪些 [SOLUTION] KK Hal Support 9 virtual sensors,这些虚拟sensor必须有sen

硬盘的分区和分区格式化类型详解

8月前

一、硬盘分区的概念分区从实质上说就是对硬盘的一种格式化。当我们创建分区时,就已经设置好了硬盘的各项物理参数,指定了硬盘主引导记录(即Master Boot Record,一

机械硬盘和固态硬盘的区别及判断硬盘类型的方法

8月前

HDD(机械硬盘)和 SSD(固态硬盘)的主要区别 存储介质 HDD:使用磁性盘片(磁盘)和机械读写头 SSD:使用闪存芯片 速度 HDD:读写速度较慢,因为需要机械读写头在磁盘上移动 SSD:读写速度较快,因为数据存储在闪存芯片上,可以

pdf转换器如何切换语言类型

8月前

现在有很多的pdf转换工具,可以将pdf等文件进行格式转换,但是关于转换工具的语言问题大家的习惯可能都不一样,有的人喜欢用中文,有的习惯用英文&

超详细的 Python 基础语句总结(多实例、视频讲解持续更新)

7月前

目录 一、运算符 1.1 + ——两个对象相加 1.2 - ——得到负数或是一个数减去另一个数 1.3 * ——两个数相乘或是返回一个被重复若干次的字符串、列表、元组 1.4——两个数相除 1.5——返回商的整数部分(向下取整

登录失败未授权用户在此计算机上win10,win10系统未授予用户请求登录类型该如何解决?...

5月前

Win10系统使用电脑时,常常会遇到win10系统未授予用户请求登录的问题。出现win10系统未授予用户请求登录的问题该怎么解决呢?就此问题,下面小编浅析win10未授予用户请求登录类型如何设置。

qq家园文字版二战风云的建筑类型

4月前

最近开发完了当年qq家园文字版的二战风云,记录下二战风云文字版的建筑类型军事区:市政厅,围墙,军校,司令部,

Linux:Linux操作系统流程控制语句-if语句使用介绍

4月前

Linux操作系统流程控制语句-if语句使用介绍本博客将介绍Linux操作系统中的流程控制语句-if语句的使用方法。我们将详细介绍单分支语句、双分支语句和多分支语句的结构和用法。此外,还会介绍文件比较、整数比对、字符

MM配置-采购-计划协议(Schedule Agreement)-定义凭证类型(SPRO-T161)

4月前

业务说明:定义采购计划协议凭证类型事务码:SPROSPRO路径:物料管理->采购->采购计划协议->定义凭证类型#1 含发布文档的计划协议1处&#x

深入解析stdole32.tlb:Windows系统中的关键类型库文件

3月前

MDI JADE 5.0:材料科学家的强大武器库

3月前

简介:MDI JADE 5.0 是一款专注于X射线衍射(XRD)数据分析的软件,适用于多个科学领域。该软件提供了从数据预处理到报告生成的全面功能,包括相鉴定、晶格参数计算、衍射峰拟合和定量分析等。JADE 5.0 的用户友好界面和兼容

热键大揭秘:一招教你解锁被同事或系统霸占的快捷键

2月前

热键侦探完全指南:揭秘被占用的Windows全局热键 一、为什么需要热键侦探? 想象一下这样的场景:你正在紧张地赶项目,想通过 Ctrl+Shift+N快速新建窗口,却发现按键毫无反应。或者在视

突破技术局限,让每一张图片在网页后台完美呈现

2月前

简介:在网页开发中,图片无法正常显示是常见但棘手的问题,可能由URL错误、MIME类型配置不当、浏览器缓存、兼容性问题或服务器设置等多种原因引起。本文结合“ie.reg”文件线索,重点分析与Internet Explorer浏览器相关

开启AutoCAD二次开发新纪元:了解新版Ribbon界面的核心功能

2月前

学如逆水行舟,不进则退。 愿自己不忘初心,坚持积累。感谢大家的支持。本篇博客主要是学习Ribbon界面,关于Ribbon界面的内容十分多,从今天开始一步步学习。在我看来,Ribbon 界面必然是CAD软件未来的主流趋势。对于绘制圆、

MySQL门外汉指南:Hadoop连不上的问题全攻略!

2月前

运行Sqoop时出现: java.sql.SQLException: Access denied for user 'root'@'hadoop-master' (using passwo

控制面板操作大全:解锁SWF播放与Flash中心的秘密

2月前

控制面板模块:   control.exe命令:   rundll32.exe   shell32.dll,Control_RunDLL结果:   显示控制面板窗口。辅助选项

SWF文件操作全解析:加载、显示与资源释放,避免Adobe Flash Player的内存泄漏陷阱

1月前

依然是先看一张运行截图: 了解过之前老版本 的童鞋们都应该清楚,对于OpenCV1.0时代的基于 C 语言接口而建的图像存储格式IplImage*,如果在退出前忘记release掉的话,就会照成内存泄露。而且用起来

从加载到显示:SWF文件在Flash中的全链路优化之路

1月前

依然是先看一张运行截图: 了解过之前老版本 的童鞋们都应该清楚,对于OpenCV1.0时代的基于 C 语言接口而建的图像存储格式IplImage*,如果在退出前忘记release掉的话,就会照成内存泄露。而且用起来

发表评论

全部评论 0
暂无评论