A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 水煮鱼000 初级黑马   /  2019-7-25 14:53  /  637 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

MyBatis工作原理
一、工作原理原型图(使用visio工具绘制)
二、工作原理分析
mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件(也可以用Java文件配置的方式,需
要添加@Configuration)中构建出SqlSessionFactory(SqlSessionFactory是线程安全的);然后,
SqlSessionFactory的实例直接开启一个SqlSession,再通过SqlSession实例获得Mapper对象并运行Mapper映射的
SQL语句,完成对数据库的CRUD和事务提交,之后关闭SqlSession。说明:SqlSession是单线程对象,因为它是非
线程安全的,是持久化操作的独享对象,类似jdbc中的Connection,底层就封装了jdbc连接。
三、 详细流程说明
1、加载mybatis全局配置文件(数据源、mapper映射文件等),解析配置文件,MyBatis基于XML配置文件生成
Configuration,和一个个MappedStatement(包括了参数映射配置、动态SQL语句、结果映射配置),其对应着
<select | update | delete | insert>标签项。
2、SqlSessionFactoryBuilder通过Configuration对象生成SqlSessionFactory,用来开启SqlSession。
3、SqlSession对象完成和数据库的交互:
a、用户程序调用mybatis接口层api(即Mapper接口中的方法)
b、SqlSession通过调用api的Statement ID找到对应的MappedStatement对象
c、通过Executor(负责动态SQL的生成和查询缓存的维护)将MappedStatement对象进行解析,sql参数转化、动
态sql拼接,生成jdbc Statement对象
d、JDBC执行sql。
e、借助MappedStatement中的结果映射关系,将返回结果转化成HashMap、JavaBean等存储结构并返回。
四、mybatis层次图
五、mybatis缓存详解
mybatis的缓存分为两级:一级缓存、二级缓存
一级缓存是SqlSession级别的缓存,缓存的数据只在SqlSession内有效
二级缓存是mapper级别的缓存,同一个namespace公用这一个缓存,所以对SqlSession是共享的。
1、一级缓存
mybatis的一级缓存是SqlSession级别的缓存,在操作数据库的时候需要先创建SqlSession会话对象,在对象中
有一个HashMap用于存储缓存数据,此HashMap是当前会话对象私有的,别的SqlSession会话对象无法访问。
具体流程:
1.第一次执行select完毕会将查到的数据写入SqlSession内的HashMap中缓存起来。
2.第二次执行select会从缓存中查数据,如果select相同切传参数一样,那么就能从缓存中返回数据,不用去数
据库了,从而提高了效率。
注意事项:
1.如果SqlSession执行了DML操作(insert、update、delete),并commit了,那么mybatis就会清空当前
SqlSession缓存中的所有缓存数据,这样可以保证缓存中的存的数据永远和数据库中一致,避免出现脏读
2.当一个SqlSession结束后那么他里面的一级缓存也就不存在了,mybatis默认是开启一级缓存,不需要配置
3.mybatis的缓存是基于[namespace:sql语句:参数]来进行缓存的,意思就是,SqlSession的HashMap存储缓存
数据时,是使用[namespace:sql:参数]作为key,查询返回的语句作为value保存的。
2、二级缓存
二级缓存是mapper级别的缓存,也就是同一个namespace的mappe.xml,当多个SqlSession使用同一个
Mapper操作数据库的时候,得到的数据会缓存在同一个二级缓存区域
二级缓存默认是没有开启的。需要在setting全局参数中配置开启二级缓存.
若想禁用当前select语句的二级缓存,添加useCache="false"修改如下:
具体流程:
1.当一个sqlseesion执行了一次select后,在关闭此session的时候,会将查询结果缓存到二级缓存
<!--如果是mybatis配置文件,做以下配置-->
<settings>
  <!--默认是false:关闭二级缓存-->
<setting name="cacheEnabled" value="true"/>
<settings
<!--当前mapper下所有语句开启二级缓存-->
<!--这里配置了一个LRU缓存,并每隔60秒刷新,最大存储512个对象,而却返回的对象是只读的-->
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
<select id="getCountByName" parameterType="java.util.Map" resultType="INTEGER"
statementType="CALLABLE" useCache="false">
2.当另一个sqlsession执行select时,首先会在他自己的一级缓存中找,如果没找到,就回去二级缓存中找,找
到了就返回,就不用去数据库了,从而减少了数据库压力提高了性能
注意事项:
1.如果SqlSession执行了DML操作(insert、update、delete),并commit了,那么mybatis就会清空当前
mapper缓存中的所有缓存数据,这样可以保证缓存中的存的数据永远和数据库中一致,避免出现脏读
2.mybatis的缓存是基于[namespace:sql语句:参数]来进行缓存的,意思就是,SqlSession的HashMap存储缓存
数据时,是使用[namespace:sql:参数]作为key,查询返回的语句作为value保存的。
3、总结
MyBatis的二级缓存相对于一级缓存来说,实现了SqlSession之间缓存数据的共享,同时粒度更加的细,能够到
namespace级别,通过Cache接口实现类不同的组合,对Cache的可控性也更强。 MyBatis在多表查询时,极大可
能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻。
在分布式环境下,由于默认的MyBatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使
用集中式缓存将MyBatis的Cache接口实现,有一定的开发成本,直接使用Redis,Memcached等分布式缓存可能成本
更低,安全性也更高。
六、MySQL常用存储引擎
注:
查询方式:
方式1:show variables like '%storage_engine%';
方式2:show engines;
修改方式:
方式1:修改my.cnf,在配置文件里面增加参数default-storage-engine,然后重启数据库服务。
[mysqld]
default-storage-engine=MyISAM
方式2:临时修改,服务重启后将会恢复。
set default-storage-engine=MyISAM
1、MyISAM
MySQL默认数据库引擎,不支持事务、外键,速度快,用于无事务要求或者select、insert为主的场景。
会创建3个文件.frm(存储表定义),.MYD(MYData,存储数据),.MYI(MYIndex,存储引擎)。
支持3中存储格式,静态(固定长度)表,动态表,压缩表。
静态表是默认格式,固定长度速度快,但是占空间大。记录长度不够时会用空格填充,读取数据时会清除
空格,存在吃尾部空格的情况。
动态表包含变长字段,记录不是固定长度,占用空间少,但是频繁更新和删除会产生随便,需要定期整
理,并且在出现故障时恢复比较困难。
压缩表由mysiampack工具创建,空间小。
2、InnoDB
提供了具有提交、回滚、崩溃恢复能力的事务安全,但是会占用更多空间用以保存数据和索引。
支持外键,创建外键的时候,要求父表必须有对应的碎银,子表在创建索引的时候也会自动创建对应的索引。
存储表和索引有两种方式,
使用共享表空间存储,表结构保存在.frm文件中,数据和索引在innodb_data_home_dir和
innodb_data_file_path定义的表空间中,可以是多个文件。
使用多表空间存储,表结构保存在.frm文件中,每个表的数据和索引单独保存在.ibd中。
3、MEMORY
使用存在于内存中的内容来创建表,访问速度快,默认使用HASH索引,服务关闭数据会丢失。
用于内容变化不频繁的代码表,或者作为统计操作的中间结果表。
MERGE:
一组MyISAM表的组合,这些表必须结构完全相同。
MERGE表本身没有数据,CRUD时其实操作的是内部的MyISAM表。
Drop只是删除MERGE的定义,对于内部表没有影响。


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马