MyBatis+Spring MVC开发指南(二)

前言

《MyBatis+Spring MVC开发指南(一)》,本篇博客将涵盖MyBatis高级映射(一对一,一对多、多对多)、延迟加载、缓存原理分析(一级缓存、二级缓存)、MyBatis和Spring的整合、逆向工程等主题。


高级映射

由于在上一篇博客中已经带大家了解了MyBatis的一些基础知识,这里的高级映射将采用Mapper代理开发方式,主要分析Mapper.xml的高级映射写法。

表:

表之间的关系

用户表User和订单表Orders是一对多的关系;

订单表Orders和订单明细表OrderDetail是一对多关系;

订单明细表OrderDetail和商品表Items是多对一关系;

一对一映射

分析:把订单以及该订单的用户信息也查询出来。

SQL层面好说,就是User和Orders的关联查询,关键是查询出来的结果如何映射?是用resultType,还是用resultMap呢?

如果使用resultType的话,显然我们的实体bean(User仅仅包含用户信息;Orders仅仅包含订单信息,没有User的引用)并不能接受关联查询的结果集,那么我们可以考虑使用OrdersQueryVO(比如说让它extends Orders,然后在加上一些User的属性)作为输出结果类型。

从上面你大致可以发现,resultType适应较简单的输出结果映射,MyBatis其实还提供了resultMap做复杂输出结果映射,比如数据库column列与字段名称不一致的映射,比如延迟加载,比如一对一,一对多,多对多等高级映射特性。


一对一映射

注意点:

第一,Orders实体对象需要有User的引用

第二,注意<association>标签中javaType必须要明确指明类型!

一对多

把订单及订单明细查询出来。

我们就考虑使用resultMap,显然这次是一对多关系(一个订单有多个订单明细)。

看一对多XML片段:

一对多映射

第一,在Orders中存在List<OrderDetail>属性。

第二,一对多使用的是<collection>标签,需要特别注意的是ofType属性,也就是需要明确指明集合对象中的类型。

多对多

其实多对多,就是<collection>和<association>的综合应用。

第一,User实体拥有List<Orders>,Orders实体拥有List<OrderDetail>,OrderDetail实体拥有List<Items>;

第二,ResultMap的编写,其实就是<collection>里面嵌套<collection>,<collection>里面嵌套<association>而已。

这里仅仅分析下映射思路,就不贴XML片段了。我想只要思路清晰,那么就会很简单。


延迟加载

所谓延迟加载,就是需要的时候才发出SQL去查询,在Hibernate中有延迟加载,MyBatis同样提供了这个功能。延迟加载需要借助<resultMap>标签完成。我们先从思路上分析下MyBatis的延迟加载:

第一,MyBatis是默认开启延迟加载的么?如果不是,那么显然应该进行延迟加载配置。

在MyBatis的全局核心配置文件SqlMapConfig.xml的<settings>中可以设置lazyLoadingEnabled以及aggressiveLazyLoading属性值。

第二,要实现延迟加载,就得进行SQL拆分。(你想想,如果我们的SQL都写在一起,DB要么执行,要么不执行,根本做不到按需查询,所以要延迟加载,就得拆分SQL。)那么怎么进行拆分呢?

在<resultMap>中的<collection>以及<association>标签中有select属性,也就是说当使用到了<collection>/<association>的时候才发出select属性对应的SQL。

第三,我们其实可以借助MyBatis去完成延迟加载,也可以自己实现延迟加载。怎么做呢?一句话,需要的时候,我们自己调用相应的Statement完成即可。


查询缓存

MyBatis是要和DB打交道的,那么自然涉及到数据查询缓存的问题,这有利于提高系统的查询效率。思考几个问题:

第一,我们知道操作DB的接口是SqlSession,那么当我们创建了SqlSession后,在这个SqlSession生命周期中,应该是可以缓存数据。比如在同一个SqlSession内部,我们发出2条相同的Statement,就可以考虑从缓存中取得数据。

第二,针对上面的SqlSession缓存,如果你稍微看一下源码,你会知道其实就是一个HashMap,KEY主要就是SqlSession+StatementId构成。

第三,既然是缓存,那么涉及到缓存和DB的数据一致问题,如果处理不好,很可能带来脏读!那么显然不仅仅是<select>需要操作SqlSession缓存呢,对于<insert>/<update>/<delete>也需要处理缓存。那么怎么处理呢?对于<insert>/<update>/<delete>的处理思路,有2种:要么更新缓存,要么清空缓存。MyBatis采取了很简单的做法,就是清空缓存!

第四,随着SqlSession的关闭,SqlSession缓存也就失效了,这也是所谓的一级缓存。还有一种缓存,是跨SqlSession的,即二级缓存。想一想,如果我们把namespace+statementId作为KEY呢?这将意味着,多个SqlSession来发出同一个Statement,可以从缓存中拿取数据。

一级、二级缓存原理图:

一级缓存、二级缓存

对于一级缓存而言,MyBatis是默认支持的,无需配置开启。而二级缓存是需要开启的,首先来说,需要在全局配置文件中指明(在<setting>中的cacheEnabled属性,全局性缓存开关),其次在需要开启二级缓存的XXXMapper.xml中指明(<cache>标签)。

MyBatis还提供了更加细粒度的缓存控制,比如在<select>标签中,就提供了useCache属性,默认为true,即使用二级缓存。(同理,<insert>标签中提供flushCache配置,显然,我们应该使用默认的true,去清空缓存)

虽然如此,但是MyBatis的二级缓存仍然不是很好用,为什么这么说呢?

假设,二级缓存中,有商品列表的数据,如果我们仅仅更新了其中一个商品,那么意味着二级缓存的清空。而我们真正想要的是刷新该商品的缓存信息而不要影响其他商品的缓存信息。

思考一个问题:缓存到哪里去呢?

缓存到本机的内存?磁盘?能够支持分布式缓存么,如ehcache、Redis?

如果你是MyBatis的作者,显然你应该提供一个Cache接口,让使用方可以自己选择缓存的具体实现!

这里,我们还需要特别注意的是,缓存对象的序列化、反序列问题(如果缓存到Redis中,那么显然涉及网络通信IO呢),应该实现Serializable接口。

看一眼MyBatis提供的Cache接口:

Cache接口

MyBatis的默认实现类:

默认Cache实现类

假设,我们需要整合ehcache的话,那么具体需要做什么呢?

第一,提供ehcache以及ehcache与MyBatis整合的依赖

第二,在<cache/>标签中,type属性指明ehcache实现Cache接口的实现类

第三,提供相关的ehcache配置文件


MyBatis和Spring整合

整合的思路(需要MyBatis-Spring整合的依赖,由MyBatis提供):

第一,SqlSessionFactory需要交给Spring管理(单例)

注意到SqlSessionFactory的创建显然需要数据库连接相关的信息,因此需要数据库连接池;除此之外还需要MyBatis的主配置文件。

第二,如果采用原始DAO的开发方法的话,那么我们是需要向Dao的实现类(交给Spring管理)中注入SqlSessionFactory,然后在各个方法中得到SqlSession进行操作的。可以让Dao的实现类extends SqlSessionDaoSupport,而SqlSessionDaoSupport类中已经存在setSqlSessionFactory()方法,因此我们可以直接向Dao的实现类注入SqlSessionFactory;另外SqlSessionDaoSupport中有SqlSession,因此使得操作更加简单呢;而且都交给Spring管理了,我们自然不必担心SqlSession的关闭忘了。

第三,如果采用Mapper代理的方式开发,那么我们需要Spring做的就是管理Mapper动态代理实现。

基于Mapper代理开发的XML片段:

Spring配置文件

我们可以指定一个包路径,告诉Spring,将这个路径下的Mapper接口+Mapper.xml都注册一下生成代理对象进行管理。


逆向工程

什么是逆向工程,说白了,就是MyBatis为我们提供了一个自动代码生成工具,这个工具可以根据数据库表信息,帮助我们生成Mapper.java/Mapper.xml/POJO实体类。

Mybatis提供了多种生成的方式,比较普遍的就是根据一个XML配置文件进行生成。在这个XML配置文件中指明DB连接信息,表信息,生成到哪里,包路径是什么等。

具体的例子,大家可以参考:http://www.mybatis.org/generator/ 进行操作即可。


到这里,这个系列文章,就写了一半了,下一篇将是关于Spring MVC~

Good Night!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,283评论 0 4
  • 非本人总结的笔记,抄点笔记复习复习。感谢传智博客及黑马程序猿成长 关联查询 数据中的表结构 数据库的分析方法 第一...
    键盘瞎阅读 1,061评论 3 5
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • Spring 技术笔记Day 1 预热知识一、 基本术语Blob类型,二进制对象Object Graph:对象图...
    OchardBird阅读 929评论 0 2
  • 官方文档 简介 入门 XML配置 XML映射文件 动态SQL Java API SQL语句构建器 日志 一、 JD...
    拾壹北阅读 3,498评论 0 52