您的位置:首页 > 其它

深入浅出Mybatis(九)延迟加载和缓存

2018-03-31 21:39 435 查看
在mybatis中,只有resultMap才具有延迟加载的功能。
1.在订单查询中实现对用户信息的延迟加载。
使用association中的select去指定延迟加载需要执行的statement的id。<!-- 延迟加载的resultMap -->
<resultMap id="ordersUserLazyLoading" type="orders">
<!-- 对订单信息进行映射配置 -->
<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(根据statement的id查询到的sql语句)
要使用userMapper.xml中完成根据用户id(user_id)用户信息的查询
column:订单信息中关联用户信息查询的列,是user_id
关联查询的sql可以理解为:
select orders.*,
(select username from user where orders.user_id=user.id) username,
(select sex from user where orders.user_id=user.id) sex
from orders
-->
<association property="user" javaType="com.beyond.mybatis.po.User" select="com.beyond.mybatis.mapper.UserMapper.selectUser" column="user_id">
</association>
</resultMap>
<!-- 查询订单关联查询用户信息,延迟加载用户信息 -->
<select id="findOrdersUserLazyLoading" resultMap="ordersUserLazyLoading">
select * from orders
</select>编写接口方法://查询订单关联查询用户,用户信息延迟加载
List<Orders> findOrdersUserLazyLoading() throws Exception;编写测试方法:
测试思路:
1、执行上边mapper方法,内部只查询了orders表
2、在程序中遍历上一步骤查询出的List<Orders>,当我们调用Orders中的getUser方法时,开始进行延迟加载。
3、延迟加载,去掉用UserMapper.xml中的selectUser这个方法获取用户信息。
首先:需要在sqlMapConfig.xml中开启延迟加载的开关。<!-- 全局参数配置 -->
<settings>
<!-- 打开延迟加载的开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
@Test
//查询订单关联查询用户,用户信息延迟加载
public void testfindOrdersUserLazyLoading() throws Exception{
SqlSession sqlSession = factory.openSession();
//通过反射拿到UserMapper的代理对象
OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
List<Orders> list = ord
4000
ersMapperCustom.findOrdersUserLazyLoading();

//遍历上边的订单列表
for (Orders orders: list) {
User user = orders.getUser();
System.out.println(user);
}

}
collection的用户可以参考association。

缓存:

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



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

    二级缓存是mapper级别的缓存,多个sqlsession去操作同一个Mapper的sql语句,多个sqlsession可以共用二级缓存,
二级缓存是跨SqlSession的。
为什么要用缓存?
如果缓存中有数据就不用从数据库中获取,大大提高系统性能。

一级缓存

下面是根据id查询用户的一级缓存:


第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户
信息。得到用户信息,将用户信息存储到一级缓存中。

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

第二次发起查询用户id位1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
mybatis默认开启了一级缓存。//一级缓存测试
public void testCache1() throws Exception{
SqlSession sqlSession = factory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

//两个都是使用的同一个sqlsession
//第一次发起请求,查询id为1的用户,从数据看查
User user1 = userMapper.selectUser(1);
System.out.println(user1);
//第二次发起请求,查询id为1的用户,从缓存中取
User user2 = userMapper.selectUser(1);
System.out.println(user2);
}

二级缓存:



首先开启mybatis的二级缓存

sqlsession1取查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。
sqlsession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。
sqlsession3去执行相同mapper下sql,执行commit提交,清空该mapper下的二级缓存区域的数据。
二级缓存与一级缓存区别:二级缓存的范围更大,多个sqlsession可以共享一个userMapper的二级缓存区域。
userMapper有一个二级缓存区域(按namespace分),其他mapper也有自己的二级缓存区域(按namespace分)
每一个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql
查询到数据将存在相同的二级缓存区域中。
开启二级缓存:
在sqlMapConfig.xml中的settings中加入(默认开启的)<!-- 开启二级缓存 -->
<setting name="cacheEnable" value="true"/>在userMapper.xml中开启二级缓存,userMapper下的sql语句执行完会存储到它的二级缓存中<mapper namespace="com.beyond.mybatis.mapper.UserMapper">

<!-- 开启本mapper的namespace下的二级缓存 -->
<cache/>

调用的pojo类实现序列化接口

为了将缓存数据取出,执行反序列化操作,因为二级缓存的存储介质是多样的,不一定在内存//二级缓存测试
public void testCache2() throws Exception{
SqlSession sqlSession1 = factory.openSession();
SqlSession sqlSession2 = factory.openSession();
SqlSession sqlSession3 = factory.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);

//两个都是使用的同一个sqlsession
//第一次发起请求,查询id为1的用户,从数据看查
User user1 = userMapper1.selectUser(1);
System.out.println(user1);

//这里执行关闭操作,将sqlsession中的数据写到二级缓存中
sqlSession1.close();

//使用sqlSession3执行commit操作
User user3 = userMapper3.selectUser(1);
user3.setUsername("king");
userMapper3.updateUser(user3);
//执行提交,清空UserMapper下边的二级缓存
sqlSession3.commit();
sqlSession3.close();

//第二次发起请求,查询id为1的用户,从缓存中取
User user2 = userMapper2.selectUser(1);
System.out.println(user2);
sqlSession2.close();
}

禁用二级缓存

<select id="selectUser" parameterType="int" resultType="user" useCache="false">
对于数据变化比较快的,且每次都要获取最新的可以禁用二级缓存。

刷新缓存:(默认为true)

<update id="updateUser" parameterType="com.beyond.mybatis.po.User" flushCache="true">

使用自定义的缓存。

1.实现cache接口(org.apache.ibatis.cache.Cache)
2.在cache标签中引用。

mybatis整合ehcache

在pom加入ehcache整合mybatis的依赖jar包<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>在UserMapper.xml中引入这个class <!-- 开启本mapper的namespace下的二级缓存 -->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: