Collection 元素
<collection property="posts" ofType="domain.blog.Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
collection 元素的作用差不多和 association 元素的作用一样。事实上,它们非常相似,以
至于再对相似点进行描述会显得冗余,因此我们只关注它们的不同点。
继续我们上面的例子,一个Blog 只有一个 Author。但一个 Blog 有许多帖子(文章)。在
Blog 类中,会像下面这样定义相应属性:
private List<Post> posts;
映射一个嵌套结果集到一个列表,我们使用collection 元素。就像 association 元素那
样,我们使用嵌套查询,或者从连接中嵌套结果集。
集合嵌套选择(Nested Select for Collection)
首先我们使用嵌套选择来加载 Blog 的文章。
<resultMap id=”blogResult” type=”Blog”>
<collection property="posts" javaType=”ArrayList” column="blog_id"
ofType="Post" select=”selectPostsForBlog”/>
</resultMap>
<select id=”selectBlog” parameterType=”int” resultMap=”blogResult”>
SELECT * FROM BLOG WHERE ID = #{id}
</select>
<select id=”selectPostsForBlog” parameterType=”int” resultType="Author">
SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>
一看上去这有许多东西需要注意,但大部分看起与我们在association元素中学过的相似。首
先,您会注意到我们使用了collection元素,然后会注意到一个新的属性“ofType”。这个元素
是用来区别JavaBean属性(或者字段)类型和集合所包括的类型。因此您会读到下面这段代码。
<collection property="posts" javaType=”ArrayList” column="blog_id"
MyBatis 3 - User Guide
41
ofType="Post" select=”selectPostsForBlog”/>
� 理解为:
“一个名为 posts,类型为 Post 的 ArrayList 集合( A collection of
posts in an ArrayList of type Post)” 。
javaType 属性不是必须的,通常MyBatis 会自动识别,所以您通常可以简略地写成:
<collection property="posts" column="blog_id" ofType="Post"
select=”selectPostsForBlog”/>
集合的嵌套结果集(Nested Results for Collection)
这时候,您可能已经猜出嵌套结果集是怎样工作的了,因为它与association 非常相似,只
不过多了一个属性“ofType”。
让我们看下这个 SQL:
<select id="selectBlog" parameterType="int" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
P.id as post_id,
P.subject as post_subject,
P.body as post_body,
from Blog B
left outer join Post P on B.id = P.blog_id
where B.id = #{id}
</select>
同样,我们把Blog 和 Post 两张表连接在一起,并且也保证列标签名在映射的时候是唯一且
无歧义的。现在将 Blog 和 Post 的集合映射在一起是多么简单:
<resultMap id="blogResult" type="Blog">
<id property=”id” column="blog_id" />
<result property="title" column="blog_title"/>
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
</resultMap>
再次强调一下,id 元素是非常重要的。如果您忘了或者不知道id 元素的作用,请先读一下
上面 association 一节。
如果希望结果映射有更好的可重用性,您可以使用下面的方式:
<resultMap id="blogResult" type="Blog">
<id property=”id” column="blog_id" />
MyBatis 3 - User Guide
42
<result property="title" column="blog_title"/>
<collection property="posts" ofType="Post" resultMap=”blogPostResult”/>
</resultMap>
<resultMap id="blogPostResult" type="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</resultMap>
� Note:
在您的映射中没有深度、宽度、联合和集合数目的限制。但应该谨记,在进行映射的
时候也要考虑性能的因素。应用程序的单元测试和性能测试帮助您发现最好的方式可能要花很长
时间。但幸运的是,MyBatis 允许您以后可以修改您的想法,这时只需要修改少量代码就行了。
关于高级联合和集合映射是一个比较深入的课题,文档只能帮您了解到这里,多做一些实
践,一切将很快变得容易理解。
Discriminator 元素
<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
</discriminator>
有时候一条数据库查询可能会返回包括各种不同的数据类型的结果集。Discriminator(识别
器)元素被设计来处理这种情况,以及其它像类继承层次情况。识别器非常好理解,它就像java
里的 switch 语句。
Discriminator定义要指定column和javaType属性。列是MyBatis 将要取出进行比较的值,
javaType 用来确定适当的测试是否正确运行(即使是String 在大部分情况下也可以工作),
例:
<resultMap id="vehicleResult" type="Vehicle">
<id property=”id” column="id" />
<result property="vin" column="vin"/>
<result property="year" column="year"/>
<result property="make" column="make"/>
<result property="model" column="model"/>
<result property="color" column="color"/>
<discriminator javaType="int" column="vehicle_type">
<case value="1" resultMap="carResult"/>
<case value="2" resultMap="truckResult"/>
<case value="3" resultMap="vanResult"/>
<case value="4" resultMap="suvResult"/>
</discriminator>
</resultMap>
在这个例子中,MyBatis 将会从结果集中取出每条记录,然后比较它的vehicle type 的值。
如果匹配任何 discriminator 中的 case,它将使用由 case 指定的resultMap。这是排它性的,换
句话说,其它的 case 的 resultMap 将会被忽略(除非使用我们下面说到的extended)。如果没
MyBatis 3 - User Guide
43
有匹配到任何 case,MyBatis 只是简单的使用定义在discriminator 块外面的 resultMap。所
以,如果 carResult 像下面这样定义:
<resultMap id="carResult" type="Car">
<result property="doorCount" column="door_count" />
</resultMap>
那么,只有doorCount属性会被加载。这样做是为了与识别器cases群组完全独立开来,哪怕
它与上一层的resultMap 一点关系都没有。在刚才的例子里我们当然知道cars和vehicles的关
系,a Car is-a Vehicle。因此,我们也要把其它属性加载进来。我们要稍稍改动一下
resultMap:
<resultMap id="carResult" type="Car" extends=”vehicleResult”>
<result property=”doorCount” column="door_count" />
</resultMap>
现在,vehicleResult 和 carResult 的所有属性都会被加载。
可能有人会认为这样扩展映射定义有一点单调了,所以还有一种可选的更加简单明了的映射
风格语法。例如:
<resultMap id="vehicleResult" type="Vehicle">
<id property=”id” column="id" />
<result property="vin" column="vin"/>
<result property="year" column="year"/>
<result property="make" column="make"/>
<result property="model" column="model"/>
<result property="color" column="color"/>
<discriminator javaType="int" column="vehicle_type">
<case value="1" resultType="carResult">
<result property=”doorCount” column="door_count" />
</case>
<case value="2" resultType="truckResult">
<result property=”boxSize” column="box_size" />
<result property=”extendedCab” column="extended_cab" />
</case>
<case value="3" resultType="vanResult">
<result property=”powerSlidingDoor” column="power_sliding_door" />
</case>
<case value="4" resultType="suvResult">
<result property=”allWheelDrive” column="all_wheel_drive" />
</case>
</discriminator>
</resultMap>
� 记住:对于这么多的结果映射,如果您不指定任何的结果集,那么MyBatis 会自动地将列名
与属性相匹配。所以上面所举的例子比实际中需要的要详细。尽管如此,大部分数据库有点复
杂,并且它并不是所有情况都是完全可以适用的。
Cache 元素
MyBatis 包含一个强大的、可配置、可定制的查询缓存机制。MyBatis 3 的缓存实现有了许
MyBatis 3 - User Guide
44
多改进,使它更强大更容易配置。默认的情况,缓存是没有开启的,除了会话缓存以外,会话缓
存可以提高性能,且能解决循环依赖。开启二级缓存,您只需要在SQL映射文件中加入简单的一
行:
<cache/>
这句简单的语句作用如下:
•
所有映射文件里的 select 语句的结果都会被缓存。
•
所有映射文件里的 insert、 update 和 delete 语句执行都会清空缓存 。
•
缓存使用最近最少使用算法(LRU)来回收。
•
缓存不会被设定的时间所清空。
•
每个缓存可以存储 1024 个列表或对象的引用(不管查询方法返回的是什么)。
•
缓存将作为“读/写”缓存,意味着检索的对象不是共享的且可以被调用者安全地修改,
而不会被其它调用者或者线程干扰。
所有这些特性都可以通过 cache 元素进行修改。例如:
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
这种高级的配置创建一个每60秒刷新一次的FIFO 缓存,存储512个结果对象或列表的引用,
并且返回的对象是只读的。因此在不用的线程里的调用者修改它们可能会引用冲突。
可用的回收算法如下:
•
LRU – 最近最少使用:移出最近最长时间内都没有被使用的对象。
•
FIFO –先进先出:移除最先进入缓存的对象。
•
SOFT – 软引用: 基于垃圾回收机制和软引用规则来移除对象(空间内存不足时才进行回
收)。
•
WEAK – 弱引用:
基于垃圾回收机制和弱引用规则(垃圾回收器扫描到时即进行回
收)。
MyBatis 3 - User Guide
45
默认使用 LRU。
flushInterval :设置任何正整数,代表一个以毫秒为单位的合理时间。默认是没有设置,因此
没有刷新间隔时间被使用,在语句每次调用时才进行刷新。
Size:属性可以设置为一个正整数,您需要留意您要缓存对象的大小和环境中可用的内存空间。
默认是1024。
readOnly:属性可以被设置为true 或false。只读缓存将对所有调用者返回同一个实例。因此这
些对象都不能被修改,这可以极大的提高性能。可写的缓存将通过序列化来返回一个缓存对象的
拷贝。这会比较慢,但是比较安全。所以默认值是false。
使用自定义缓存
除了上面已经定义好的缓存方式,您能够通过您自己的缓存实现来完全重写缓存行为,或者
通过创建第三方缓存解决方案的适配器。
<cache type=”com.domain.something.MyCustomCache”/>
这个例子演示了如果自定义缓存实现。由 type 指定的类必须实现 org.mybatis.cache.Cache
接口。这个接口是 MyBatis 框架比较复杂的接口之一,先给个示例:
public interface Cache {
String getId();
int getSize();
void putObject(Object key, Object value);
Object getObject(Object key);
boolean hasKey(Object key);
Object removeObject(Object key);
void clear();
ReadWriteLock getReadWriteLock();
}
要配置您的缓存,简单地添加一个公共的JavaBeans 属性到您的缓存实现中,然后通过cache
元素设置属性进行传递,下面示例,将在您的缓存实现上调用一个setCacheFile(String file)方
法。
<cache type=”com.domain.something.MyCustomCache”>
<property name=”cacheFile” value=”/tmp/my-custom-cache.tmp”/>
</cache>
您可以使用所有简单的JavaBeans 属性,MyBatis 会自动进行转换。
MyBatis 3 - User Guide
46
需要牢记的是一个缓存配置和缓存实例都绑定到一个SQL Map 文件命名空间。因此,所有的
这个相同命名空间的语句也都和这个缓存绑定。语句可以修改如何与这个缓存相匹配,或者使用
两个简单的属性来完全排除它们自己。默认情况下,语句像下面这样来配置:
<select ... flushCache=”false” useCache=”true”/>
<insert ... flushCache=”true”/>
<update ... flushCache=”true”/>
<delete ... flushCache=”true”/>
因为有默认值,所以您不需要使用这种方式明确地配置这些语句。如果您想改变默认的动
作,只需要设置flushCache和useCache 属性即可。举个例子来说,在许多的场合下您可能排除缓
存中某些特定的select语句。或者您想用select语句清空缓存。同样的,您也可能有一些update
语句在执行的时候不需要清空缓存。
cache-ref 元素
回想上一节,我们仅仅只是讨论在某一个命名空间里使用或者刷新缓存。但有可能您想要在
不同的命名空间里共享同一个缓存配置或者实例。在这种情况下,您就可以使用cache-ref 元素
来引用另外一个缓存。
<cache-ref namespace=”com.someone.application.data.SomeMapper”/>
- 浏览: 189256 次
- 性别:
- 来自: 北京
最新评论
-
ZZX19880809:
没看到有[x] Received 'hello word!0' ...
rabbitmq学习3:Publish/Subscribe -
ZZX19880809:
根本就没有. 应该输入first message.
rabbitmq学习2:Work Queues -
jiaofuyou:
独孤日日也 写道我亲自试验了并没有实现啊,第一个worker输 ...
rabbitmq学习2:Work Queues -
独孤日日也:
我亲自试验了并没有实现啊,第一个worker输出: Wait ...
rabbitmq学习2:Work Queues -
jiaofuyou:
想问个问题,象这种任务分发的工作队列,你举的例子是一个队列被多 ...
rabbitmq学习2:Work Queues
相关推荐
8. **一对一、一对多、多对多关系映射**:MyBatis提供了处理复杂关联关系的能力,通过association和collection元素实现。 9. **缓存机制**:MyBatis内置了两级缓存,一级缓存在SqlSession级别,二级缓存在Mapper...
虽然具体的压缩包内容无法直接查看,但从上述信息可以推断,这个教程将为学习者提供一个全面的指南,教他们如何在Mybatis中处理复杂的数据库关系映射,以提升Java应用的数据访问能力。为了深入理解和掌握这些知识,...
此部分涵盖了 MyBatis 的一系列教程,从环境搭建到具体功能的实现,旨在帮助初学者快速掌握 MyBatis 的使用。 以上是关于 MyBatis 的详细介绍,包括其基本概念、配置、SQL 映射文件、动态 SQL、缓存、懒加载以及...
MyBatis还支持高级结果映射,例如resultMap元素、id/result元素、Constructor元素、Association元素、Collection元素和Discriminator元素,这些元素允许开发者创建复杂的结果映射。 Cache元素和cache-ref元素分别...
"Mybatis学习(四)解决表字段名和实体类属性名不相同的冲突.docx"可能讨论了如何处理数据库字段名与Java实体类属性名不一致的情况。Mybatis通过别名(aliases)或者注解(@Column)来实现字段映射,使得两者可以...
《MyBatis 深入浅出》是一本旨在引导初学者从入门到精通的教程,专注于MyBatis这一流行的Java持久层框架。MyBatis是一个优秀的轻量级框架,它解决了传统JDBC中的繁琐代码问题,使得数据库操作更加简便易行。本教程将...
Mybatis是中国著名的开源持久层框架,它为Java开发者提供了方便快捷的数据映射功能,使得数据库操作变得更加简单...同时,也可以结合Mybatis官方文档和视频教程,系统地学习和掌握这些知识点,提升你的数据库操作技能。
在本教程中,我们将深入探讨MyBatis的第10章及后续章节的知识点,这些章节通常涵盖了一些进阶主题,包括但不限于动态SQL、结果映射、缓存机制、插件、事务管理等。下面,让我们逐一解析这些关键概念。 1. **动态SQL...
对于复杂类型的映射,还可以使用association和collection元素处理一对多、一对一的关系。 事务管理在MyBatis中也很重要。默认情况下,MyBatis使用JDBC的默认事务管理,但可以通过配置自定义事务管理器,实现Spring...
【尚硅谷_myBatis】是针对myBatis框架的一个学习资源集合,主要针对初学者,提供了详尽的文档和视频教程。myBatis是一个优秀的Java持久层框架,它支持定制化SQL、存储过程以及高级映射。这个压缩包内可能包含的资料...
这篇教程将带你深入理解 MyBatis 的核心概念和使用方法。 **一、MyBatis 概述** MyBatis 由 Paweł Piech 创立,最初名为 iBatis,后来改名为 MyBatis。MyBatis 旨在简化数据库操作,通过 XML 或注解方式配置和映射...
在Mybatis中,可以通过编写多表联查的SQL语句,或者使用Mapper的association和collection元素来处理复杂的联合查询。例如,通过LEFT JOIN可以获取所有左表记录,即使在右表中没有匹配项,而RIGHT JOIN则反之。FULL ...
在本教程中,我们将通过一个具体的应用场景来详细介绍如何使用 MyBatis 进行 CRUD 操作。该应用场景是实现一个名为“tlias智能学习辅助系统”的员工管理系统,包括员工的增删改查等基本功能。 ##### 2.1 查询 **...
总结,学习Mapper基础教程,需要理解Mapper在MyBatis中的作用,掌握配置、使用以及优化方法,这将有助于你更高效地进行Java Web开发中的数据库操作。通过实践和不断的探索,你将能够更好地利用Mapper进行复杂的数据...
【描述】: "ibatis的教程5个文档,适合初学者学习" 提供了一套完整的Ibatis学习路径,帮助新手逐步掌握这一强大的持久层框架。 【知识点详解】: Ibatis,全称为“Java SQL Mapping Framework”,是一个优秀的轻...
总之,iBatis是一个强大的工具,通过本教程的学习,开发者可以熟练地运用它来构建高效、可维护的数据访问层。在实际开发中,结合MyBatis(iBatis的升级版)的高级特性,如注解支持、自动映射和插件扩展,能进一步...