- 数据模型分析思路
- 每张表记录的数据内容
- 分模块对每张表记录对内容进行熟悉,相当于学习系统需求(功能)的过程
- 每张表重要的字段设置
- 非空字段、外键字段
- 数据库级别表与表之间的关系
- 外键关系
- 表与表之间的业务关系
- 在分析表与表之间的业务关系时一定要建立在某个业务意义基础上去分析
- 每张表记录的数据内容
- 延时加载
- 什么是延时加载
- 先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表比关联查询多表速度要快。
- mybatis默认没有开启延迟加载,需要在SqlMapConfig.xml中setting设置
-
<settings> <!-- 全局设置懒加载,如果设为'false',则所以相关联的都会初始化加载 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 当设置为'true'的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载 --> <setting name="aggressiveLoadingEnabled" value="false"/> </settings>
-
<!-- 可以使用继承extends,来避免代码重复配置 --> <resultMap id="userResultMap" type="cn.xxx.mybatis.po.User" extends=""> <!-- id标识查询结果集中唯一标识 column:查询出来的列名 property:type指定的pojo类型中的属性名 最终resultMap对column和property作一个映射关系(对应关系) --> <id column="id_" property="id"/> <!-- result:对普通名映射定义 column:查询出来对列名 property:type指定对pojo类型中对属性名 最终resultMap对column和property做一个映射关系(对应关系) --> <result column="username_" property="username"/> <!-- 配置映射的关联的用户信息 --> <!-- association:用于映射关联查询单个对象的信息 property:要将关联查询的用户信息映射到指定表user中的那个属性 select:指定延迟加载需要执行的statement的id,若查询的statement的id不在当前的mapper中,需要在statement的id前面加namespace column:表中关联延迟表查询的列 --> <association property="" javaType="" > <!--id标识查询结果集中唯一标识 column:查询出来的列名 property:type指定的pojo类型中的属性名 最终resultMap对column和property作一个映射关系(对应关系)--> <id column="" property=""/> <result column="" property=""/> </association> <!-- collection:对关联查询到多条记录映射到集合对象中 property:将关联查询到到多条记录映射到type的指定属性名中 ofType:指定映射到list集合属性中pojo的类型 --> <collection property="" ofType=""> <id column="" property=""/> <result column="" property=""/> </collection> </resultMap>
- 什么是延时加载
- 查询缓存
- 什么是查询缓存
- mybatis提供查询缓存,用于减轻数据压力提高数据库性能
- mybatis提供一级缓存、二级缓存
- 一级缓存
- 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造SqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的SqlSession之间的缓存数据区域(HashMap)是互不影响的
- 二级缓存
- 二级缓存是Mapper级别的缓存,多个SqlSession去操作同一个Mapper的Sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的
- 每一个namespace的mapper都有一个二级缓存区;拥有相同的namespace的mapper,拥有共同的二级缓存区
- 使用场景
- 对于访问多的查询请求且用户对查询结果实时性要求不高。例如耗时较高的统计分析sql、电话账单查询sql等。
- 局限性
- mybatis二级缓存对细粒度的数据级别的缓存时间不好。例如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新对商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新商品的缓存信息而不刷新其它商品信息。因为mybatis的二级缓存区域以单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。
- 除了在SqlMapConfig.xml设置二级缓存的总开关,还需要在具体的mapper.xml中开启二级缓存
-
<!-- SqlMapConfig.xml配置 --> <!-- 二级缓存 --> <settings> <!-- 对在此配置文件下对所有cache进行全局性开/关设置 --> <setting name="cacheEnabled" value="true"/> </settings> <!-- mapper.xml配置 --> <!-- type:指定cache接口对实现类的类型 flushInterval:刷新间隔,取值为任意正整数。代表一个合理的毫秒形式的时间段,若不设置则没有刷新间隔,缓存仅仅调用语句时刷新 size:引用数目,取值为任意正整数。要记住缓存的对象数目和运行环境的可用内存资源数目。默认值1024 readOnly:只读,设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。这些对象不能被修改。 这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但安全。因此默认是False。 --> <!-- 加入ehcache-core-2.6.8.jar和mybatis-ehcache-1.0.3.jar两个jar包,配置mapper中的cache中的type为ehcache对cache接口对实现类型 --> <cache type="org.mybatis.caches.ehcache.EhcacheCache" flushInterval="5" size="1024" readOnly="false"/> <!-- 针对每次查询需要最新数据的sql,要设置useCache='false',禁用二级缓存 --> <select id="selectXXX" resultType="xxx" useCache="false"> select * from xxx </select> <!-- 一般情况下执行完commit操作都需要刷新缓存, flushCache='true'表示刷新缓存,这样可以避免数据库脏读 --> <insert id="insertXxx" parameterType="cn.xxx.mybatis.po.xxx" flushCache="true"> <!-- 为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一样在内存 --> <!-- pojo接口反序列化 -->
-
- 为什么要使用缓存
- 如果缓存中有数据就不用从数据库中获取,大大提高系统性能。
- 什么是查询缓存
- mybatis整合ehcache
- ehcache是一个分布式缓存框架
- 为什么要使用分布缓存
- 不使用分布缓存,缓存的数据在各个服务器单独存储,不方便系统开发。所以要使用分布式缓存对缓存数据进行集中管理。
- 为什么要整合
- mybatis无法实现分布式缓存,需要和其他分布式缓存框架进行整合
- 如果整合
- 实现Cache接口
-
<!-- 加入ehcache-core-2.6.8.jar和mybatis-ehcache-1.0.3.jar两个jar包,配置mapper中的cache中的type为ehcache对cache接口对实现类型 --> <cache type="org.mybatis.caches.ehcache.EhcacheCache" flushInterval="5" size="1024" readOnly="false"/> <!-- 创建一个ehcache的配置文件 --> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- --> <diskStore path="java.io.tmpdir"/> <!-- maxElementsInMemory: eternal: timeToIdleSeconds: timeToLiveSeconds: maxElementsOnDisk: diskExpiryThreadIntervalSeconds: memoryStoreEvictionPolicy: --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> <!-- --> <persistence strategy="localTempSwap"/> </defaultCache> </ehcache>
-
- 实现Cache接口