高级结果映射
MyBatis的创建基于这样一个思想:数据库并不是您想怎样就怎样的。虽然我们希望所有的数据库遵守第三范式或BCNF(修正的第三范式),但它们不是。如果有一个数据库能够完美映射到所有应用程序,也将是非常棒的,但也没有。结果集映射就是MyBatis为解决这些问题而提供的解决方案。例如,我们如何映射下面这条语句?
您可能想要把它映射到一个智能的对象模型,包括由一个作者写的一个博客,有许多文章( Post ,帖子 ),每个文章由0个或者多个评论和标签。下面是一个复杂ResultMap 的完整例子(假定作者、博客、文章、评论和标签都是别名)。仔细看看这个例子,但是不用太担心,我们会一步步地来分析,一眼看上去可能让人沮丧,但是实际上非常简单的
这个resultMap 的元素的子元素比较多,讨论起来比较宽泛。下面我们从概念上概览一下这个resultMap的元素。
resultMap
·constructor–实例化的时候通过构造器将结果集注入到类中
oidArg– ID 参数; 将结果集标记为ID,以方便全局调用
oarg–注入构造器的结果集
·id–结果集ID,将结果集标记为ID,以方便全局调用
·result–注入一个字段或者javabean属性的结果
·association–复杂类型联合;许多查询结果合成这个类型
o嵌套结果映射– associations能引用自身,或者从其它地方引用
·collection–复杂类型集合
o嵌套结果映射– collections能引用自身,或者从其它地方引用
·discriminator–使用一个结果值以决定使用哪个resultMap
ocase–基于不同值的结果映射
§嵌套结果映射–case也能引用它自身, 所以也能包含这些同样的元素。它也可以从外部引用resultMap
è最佳实践:逐步地生成resultMap,单元测试对此非常有帮助。如果您尝试一下子就生成像上面这样巨大的resultMap,可能会出错,并且工作起来非常吃力。从简单地开始,再一步步地扩展,并且进行单元测试。使用框架开发有一个缺点,它们有时像是一个黑合。为了确保达到您所预想的行为,最好的方式就是进行单元测试。这对提交bugs 也非常有用。
下一节,我们一步步地查看这些细节。
id, result元素
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
这是最基本的结果集映射。id 和result 将列映射到属性或简单的数据类型字段(String, int, double, Date等)。
这两者唯一不同的是,在比较对象实例时id 作为结果集的标识属性。这有助于提高总体性能,特别是应用缓存和嵌套结果映射的时候。
Id、result属性如下:
Attribute |
Description |
property |
映射数据库列的字段或属性。如果JavaBean 的属性与给定的名称匹配,就会使用匹配的名字。否则,MyBatis 将搜索给定名称的字段。两种情况下您都可以使用逗点的属性形式。比如,您可以映射到“username”,也可以映射到“address.street.number”。 |
column |
数据库的列名或者列标签别名。与传递给resultSet.getString(columnName)的参数名称相同。 |
javaType |
完整java类名或别名(参考上面的内置别名列表)。如果映射到一个JavaBean,那MyBatis 通常会自行检测到。然而,如果映射到一个HashMap,那您应该明确指定javaType 来确保所需行为。 |
jdbcType |
这张表下面支持的JDBC类型列表列出的JDBC类型。这个属性只在insert,update或delete 的时候针对允许空的列有用。JDBC 需要这项,但MyBatis 不需要。如果您直接编写JDBC代码,在允许为空值的情况下需要指定这个类型。 |
typeHandler |
我们已经在文档中讨论过默认类型处理器。使用这个属性可以重写默认类型处理器。它的值可以是一个TypeHandler实现的完整类名,也可以是一个类型别名。 |
支持的JDBC类型
MyBatis支持如下的JDBC类型:
BIT |
FLOAT |
CHAR |
TIMESTAMP |
OTHER |
UNDEFINED |
TINYINT |
REAL |
VARCHAR |
BINARY |
BLOB |
NVARCHAR |
SMALLINT |
DOUBLE |
LONGVARCHAR |
VARBINARY |
CLOB |
NCHAR |
INTEGER |
NUMERIC |
DATE |
LONGVARBINARY |