| 
 
| 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的定义,对于内部表没有影响。
 
 
 
 | 
 |