框架2 MyBatis

参考:
MyBatis结构和组件 //www.greatytc.com/p/75a6a2297c69
MyBatis运行流程、缓存和插件 //www.greatytc.com/p/4fe280c44294
MyBatis缓存
//www.greatytc.com/p/7a98dda8cd75
//www.greatytc.com/p/8801d1aa20a0
MyBatis常见面试题 https://blog.csdn.net/a745233700/article/details/80977133

一.MyBatis概述

1.MyBatis
  • 支持普通SQL查询、存储过程和高级映射的持久层框架
  • 消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的封装
  • MyBatis可使用XML或注解进行配置,将接口和Java的POJO映射成数据库记录
  • 专注于Sql本身,适用于对性能要求很高或需求变化较多的项目
2.MyBatis特点
  • 优点
    1)简单易学。MyBatis本身小而简单
    2)灵活。MyBatis允许自由编写Sql语句
    3)Sql和程序代码解耦,且提供xml标签支持编写动态sql
    4)提供映射标签,支持对象与数据库的ORM字段关系映射
    5)与JDBC相比,减少了50%以上的代码量
  • 缺点
    1)自由编写Sql语句意味较大的工作量
    2)Sql语句依赖于数据库,导致数据库无法随意更换,移植性差

二.MyBatis原理

1.MyBatis功能结构
  • API接口层
    开发人员通过接口API操纵数据库,接口层接收请求后会调用数据处理层完成具体的数据处理
  • 数据处理层
    根据API接口层调用的请求完成一次数据库操作,负责具体的Sql查找、Sql解析和执行结果映射处理等
  • 基础支撑层
    实现连接管理、事务管理和执行结果映射处理等基础功能,为数据处理层提供基础支持
MyBatis功能结构
2.MyBatis运行流程
  • 加载配置
    从配置文件或注解获取配置信息并加载成MappedStatement对象,此对象=传入参数的映射配置+要执行的Sql语句+结果的映射配置
  • Sql解析
    API接口层接收调用请求时,根据传入的Sql的Id找到对应的MappedStatement,再根据传入的参数对象解析MappedStatement获得最终要执行的Sql语句和参数
  • Sql执行
    获取数据库连接执行Sql解析获得的Sql语句和参数,并返回结果
  • 结果映射
    将数据库返回结果按映射配置转换成需要的数据类型并返回
MyBatis运行流程
3.MyBatis主要构件
  • SqlSession
    MyBatis主要顶层API,负责和数据库交互的会话,完成增删查改操作
  • Executor
    MyBatis执行器,是MyBatis调度和核心,负责Sql语句生成和查询缓存的维护
  • StatementHandler
    封装了JDBC Statement,负责JDBC中对Statement的操作,如设置参数、将Statement结果集转换为List集合
  • ParameterHandler
    将用户传递的参数转换为JDBC Statement所需的参数
  • ResultSetHandler
    将JDBC返回的ResultSet结果集转换为List集合
  • TypeHandler
    负责Java数据类型和JDBC数据类型间的映射和转换
  • MappedStatement
    维护<select/update/delete/insert>节点的封装
  • SqlSource
    根据用户传递的parameterObject,动态生成Sql语句,将信息封装到BoundSql对象并返回
  • BoundSql
    表示动态生成的Sql语句及相应的参数信息
  • Configuration
    维持MyBatis所有的配置信息
MyBatis主要组件及其相互关系

三.MyBatis缓存

1.缓存总览
MyBatis流程图
  • 缓存在流程的Executor使用,Executor执行查询时先判断缓存,若缓存命中,直接返回缓存中的结果,否则继续之后的步骤查询数据库
  • MyBatis使用底层为HashMap的Cache对象,通过各种装饰类对其层层装饰,以实现各种功能和隔离不同功能逻辑
  • MyBatis缓存分为一级缓存二级缓存,默认开启一级缓存
  • 数据查询优先级:二级缓存---一级缓存---数据库
2.一级缓存
  • 缓存默认Session级别(可设为Statement),同一会话的重复Sql语句可使用缓存
  • 不同Session间缓存相互独立,分布式查询可能读到脏数据
  • Executor收到Sql语句后,先查询自己的localCache(HashMap),缓存命中则直接返回结果,缓存命中失败则继续查询数据库后将结果写入localCache
3.二级缓存
  • 解决跨SqlSession的缓存问题,MyBatis提供二级缓存功能
  • 二级缓存使用CachingExecutor包装Executor,CachingExecutor负责与全局二级缓存交互
二级缓存流程图
  • CachingExecutor优先查询二级缓存,如没有匹配则委托给它包装的Executor匹配的一级缓存
Executor
  • 二级缓存全局有效,划分到mapper级别(namespace定义),而非整个application使用同一缓存
  • 由于不同namespace的二级缓存相互独立,多表查询时容易出现脏数据。如果将多个表的操作放在相同namespace会导致缓存颗粒度过大,频繁刷新缓存
  • MyBatis Cache是基于本地的,分布式环境下必然会读取脏数据,用户自定义实现MyBatis的Cache接口开发成本较高,直接使用Redis/Memcached等分布式缓存成本更低,安全性更高

四.MyBatis插件

1.插件概述
  • MyBatis插件又称拦截器,采用责任链模式,通过动态代理组织多个插件(拦截器),改变MyBatis默认行为(如Sql重写)
  • 插件通过动态代理方式在已映射语句执行过程中的某一点进行拦截调用
  • MyBatis插件需要实现Interceptor接口,该接口主要方法有
    1)setProperties:配置MyBatis插件的自定义属性
    2)plugin:插件用来封装目标对象的方法,通过该方法可返回目标对象本身或一个它的代理
    3)interceptor:拦截时执行的方法
    4)plugin接口

五.MyBatis与其他框架

1.MyBatis与iBatis
  • iBatis是Apache的一个开源项目,该项目在2010年从Apache Software Foundation迁移到Google Code,并改名MyBatis
  • MyBatis是IBatis的升级版,MyBatis在以下方面改善了IBatis功能
    1)MyBatis实现接口绑定,使用更方便
    2)MyBatis改进了对象关系映射(association和collection)
    3)MyBatis在动态Sql语句中采用OGNL表达式取代节点配置
2.MyBatis与Hibernate
  • MyBatis
    1)Mybatis真正实现了Java代码和Sql分离
    2)Mybatis自行编写sql,灵活度高,便于Sql优化
  • Hibernate
    1)Hibernate数据库无关性好,适用于需求固定的定制化软件,但学习成本高
    2)Hibernate大大降低了对象和数据库的耦合度,其数据移植性远大于MyBatis
    3)Hibernate在多表关联查询时表现较差
    4)Hibernate效率较低,Sql自动生成,不便于人工优化,调优需要相当经验积累
  • 场景选择
    1)数据量大(超过千万级别的表/单次业务大批量数据(百万条)提交或读取)适用MyBatis
    2)表关联度(主要业务表的关联表>20)复杂适用MyBatis

六.常见面试题

1.SqlSession创建过程和相关对象生命周期?
  • SqlSessionFactoryBuilder---SqlSessionFactory---SqlSession---SqlMapper
  • SqlSessionFactoryBuilder在构建SqlSessionFactory后即可销毁
  • SqlSessionFactory存在于整个MyBatis应用中,类似数据库连接池,不断创建SqlSession
  • SqlSession类似于数据库连接,在完成一次业务请求后回收
  • SqlMapperSqlSession创建,生命周期SqlMapper<=SqlSession
2.#{}和${}的区别?
  • 前者’#{}‘是预编译处理,MyBatis预编译时会将#{}替换为?号,调用PreparedStatement的set方法赋值
  • 后者是xml文件的字符串替换,MyBatis会把${}替换成变量的值
  • 使用#{}可防止Sql注入,提高安全性
3.实体类的属性名和表中字段名不一样该如何映射?
  • 在Sql语句中定义与实体类属性名一样的别名
  • 通过<resultMap>映射字段名和实体类属性名
    <select id="getOrder" parameterType="int" resultMap="orderresultmap">
        select * from orders where order_id=#{id}
    </select>
 
   <resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
        <!–用id属性来映射主键字段–>
        <id property=”id” column=”order_id”>
 
        <!–用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性–>
        <result property = “orderno” column =”order_no”/>
        <result property=”price” column=”order_price” />
    </reslutMap>
4.每个xml映射文件都有一个Dao接口与之对应,Dao接口的工作原理是什么?Dao接口里的方法在参数不同时是否可以重载?
  • Dao接口即Mapper接口:映射的xml文件的namespace接口的全限定名;映射文件中MappedStatement的id接口的方法名;接口方法的参数就是传递给sql的参数
  • 调用接口方法时,通过接口全限定名+方法名定位唯一的MappedStatement
  • 由于仅使用接口全限定名和方法名定位MappedStatement,故不同参数的接口方法不能重载
  • 此外,不同的xml配置文件,如果设置不同的namespace,则id可重复,否则不可重复
5.MyBatis是如何进行分页的?分页插件的原理是什么?
  • MyBatis使用RowBounds对象针对ResultSet结果集执行内存分页,也可以在Sql内直接书写带有物理分页的参数实现物理分页
  • 分页插件实现MyBatis提供的插件接口,在插件的拦截方法里拦截并重写待执行的sql
6.MyBatis动态Sql是做什么的?其执行原理是什么?
  • MyBatis允许在xml映射文件中以标签形式编写动态Sql,完成逻辑判断和动态拼接Sql的功能
  • MyBatis提供 trim | where | set | foreach | if | choose | when | otherwise | bid 9种动态sql标签
  • 执行原理为
    1)使用OGNL从sql参数对象中计算表达式的值
    2)根据表达式值动态拼接Sql
7.MyBatis是否支持延迟加载?其实现原理是什么?
  • 延迟加载又称懒加载,用于处理N+1性能问题
  • N+1问题指映射集合(resultMap)级联时,我们需要的数据少于数据库查出的数据,浪费性能且加重数据库负担
  • MyBatis仅支持association关联对象(1对1)和collection关联集合(1对多)的延迟加载,配置文件中参数LazyLoadingEnabled=true|false设置是否开启延迟加载
  • MyBatis通过动态代理实现延迟加载
    参考:https://my.oschina.net/wenjinglian/blog/1857581?from=singlemessage
8.使用MyBatis的mapper接口调用时有哪些要求?
  • Mapper接口方法名和mapper.xml定义的sql的id相同
  • Mapper接口方法的输入参数类型和mapper.xml定义的sql的parameterType类型相同
  • Mapper接口方法的输出参数类型和mapper.xml定义的sql的resultType类型相同
  • Mapper.xml的namespace即是mapper接口的类路径
9.mapper有哪几种编写方式?
  • 接口实现类继承SqlSessionDaoSupport类
  • 使用org.mybatis.spring.mapper.MapperFactoryBean
  • 使用mapper扫描器
10.mapper如何传递多个参数?
  • xml使用#{0}接收dao层第一个参数,#{1}接收第二个参数,以此类推
  • 使用@param注解
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容