mybatis开发(第三天)

延迟加载

resultMap可以实现高级映射(使用associationcollection实现一对一及一对多映射),associationcollection具备延迟加载功能。

需求:

如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。

延迟加载:先从单表查询、需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

需要定义两个mapper的方法对应的statement
1.只查询订单信息
select * from orders
2.关联查询用户信息
  通过上边查询到的订单信息中的user_id去关联查询用户信息
<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLazyLoading">
<!-- 实现用户信息的延迟加载 -->
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>

<!-- select:指定延迟加载需要执行的statement的id(是根据user_id查询用户信息的statement)
column :订单信息中关联用户信息查询的列,是user_id-->
<association property="user" javaType="cn.itcast.mybatis.po.User" select="cn.itcast.mybatis.mapper.UserMapper.findUserById" column="user_id">
<!-- 实现用户信息的延迟加载 -->
</association>
</resultMap>

<select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoading">
SELECT * FROM orders
</select>

开启延迟加载:

<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
测试方法:
@Test
public void testfindOrdersUserLazyLoading() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
List<Orders> list = ordersMapper.findOrdersUserLazyLoading();
for(Orders orders:list){
User user = orders.getUser();
System.out.println(user);


}
一级缓存:

mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。

mybaits提供一级缓存,和二级缓存。



一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mappersql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

一级缓存的工作原理:


第一次发起查询用户id1的用户信息,先去找缓存中是否有id1的用户信息,如果没有,从数据库查询用户信息。

得到用户信息,将用户信息存储到一级缓存中。

 

如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读

 

第二次发起查询用户id1的用户信息,先去找缓存中是否有id1的用户信息,缓存中有,直接从缓存中获取用户信息。

二级缓存:


首先开启mybatis的二级缓存。

sqlSession1去查询用户id1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。

如果SqlSession3去执行相同 mappersql,执行commit提交,清空该 mapper下的二级缓存区域的数据。

sqlSession2去查询用户id1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。

 

二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。

UserMapper有一个二级缓存区域(按namespace分) ,其它mapper也有自己的二级缓存区域(按namespace分)。

每一个namespacemapper都有一个二缓存区域,两个mappernamespace如果相同,这两个mapper执行sql查询到数据将存在相同 的二级缓存区域中。

开启二级缓存

mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。

在核心配置文件SqlMapConfig.xml中加入

<setting name="cacheEnabled" value="true"/>

开启具体的mapper下的二级缓存:

<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">

<!-- 开启本map的二级缓存 -->
<cache></cache>

然后进行序列化po,(序列化的是使用在能够查询的po类上面):

public class User implements Serializable{


private int id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Orders> ordersList;

为了将缓存数据取出执行反序列化的操作,因为二级缓存数据存储介质多种多样,不一定在内存中。

useCache配置

statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

 

总结:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。

刷新缓存(就是清空缓存)

mapper的同一个namespace中,如果有其它insertupdatedelete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。

 

 设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。

如下:

<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">

 

总结:一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读

mybatis整合ehcache

分布缓存:

不使用分布缓存,缓存的数据在各个服务单独存储,不方便系统的开发。所以要使用分布缓存。
mybatis提供一个cache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。
mybatis和ehcache整合,mybatis和ehcache整合包中提供一个cache接口的实现类。
public interface Cache {


  /**
   * @return The identifier of this cache
   */
  String getId();


  /**
   * @param key Can be any object but usually it is a {@link CacheKey}
   * @param value The result of a select.
   */
  void putObject(Object key, Object value);


  /**
   * @param key The key
   * @return The object stored in the cache.
   */
  Object getObject(Object key);

加入jar包:


整合ehcache:

<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

加入ehcache的配置文件

classpath下添加:ehcache.xml

内容如下:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

<diskStore path="F:\develop\ehcache" />

<defaultCache 

maxElementsInMemory="1000" 

maxElementsOnDisk="10000000"

eternal="false" 

overflowToDisk="false" 

timeToIdleSeconds="120"

timeToLiveSeconds="120" 

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU">

</defaultCache>

</ehcache>




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值