1 延迟加载
延迟加载也叫做懒加载lazy
按需要进行加载,是优化查询速度的方法
Mybatis中有两个标签支持延迟加载
<association>
<collection>
操作步骤:
1. 打开延迟加载开关,关闭积极加载开关
核心配置文件sqlMapconfig.xml
<settings> <!-- 打开延迟加载开关 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 关闭积极加载开关 --> <setting name="aggressiveLazyLoading" value="false"/> </settings> |
2. 编写代码
映射文件:
<resultMap type="cn.itcast.po.Orders" id="orderAndUserLazyResultMap"> <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:调用要执行的sql语句,使用那个sql的namespace+.+sql语句的id 例如:cn.itcast.mapper.UserMapper.findUserById column:是orders表中与user表关联的字段 --> <association property="user" javaType="cn.itcast.po.User" select="cn.itcast.mapper.UserMapper.findUserById" column="user_id"> </association> </resultMap>
<select id="findOrderAndUserLazy" resultMap="orderAndUserLazyResultMap"> select * from orders </select> |
接口:
public List<Orders> findOrderAndUserLazy(); |
测试代码:
@Test public void testFindOrderAndUserLazy() throws Exception{ SqlSession openSession = sqlSessionFactory.openSession(); OrdersMapper ordersMapper = openSession.getMapper(OrdersMapper.class); List<Orders> list = ordersMapper.findOrderAndUserLazy(); for(Orders order : list){ String number = order.getNumber(); System.out.println(number); User user = order.getUser(); System.out.println(user.getUsername()); } } |
2 总结
1. 对单个对象的映射关系使用:<association
2. 对集合对象的映射关系使用:<collection
3. 延迟加载:需要在核心配置文件中配置开关;在mybatis中association和collection支持延迟加载
3 缓存
优化查询速度
3.1 一级缓存
是SqlSession级别的,一级缓存由mybatis自己控制,不需要人为干预
1. 第一次查询会查询一级缓存,如果缓存中没有数据会从数据库中查询
2. 如果有更新、删除、修改操作,那么会清空缓存
3. 接着再次执行查询则会去数据库中查询数据并放到缓存中
4. 再次查询则直接从缓存中查询数据
映射文件:
<select id="findUserByIdCache1" parameterType="int" resultType="user"> select * from User where id=#{aaa} </select> |
接口:
public User findUserByIdCache1(Integer id); |
测试代码:
@Test public void testFindUserByIdCache1() throws Exception{ SqlSession openSession = sqlSessionFactory.openSession(); //获得Mapper对象 UserMapper userMapper = openSession.getMapper(UserMapper.class); //第一次查询 User user1 = userMapper.findUserByIdCache1(1); System.out.println(user1); user1.setUsername("李四"); userMapper.updateUserById(user1); openSession.commit(); //第二次查询 User user2 = userMapper.findUserByIdCache1(1); System.out.println(user2); } |
3.2 二级缓存
二级缓存中的数据可以存储在内存中,或者硬盘中。
操作步骤:
1. 开启二级缓存
在SqlMapConfig.xml中加入
<!-- 开启二级缓存 --> <setting name="cacheEnabled" value="true"/> |
2. 在需要二级缓存的映射文件中加入<cache />
在UserMapper.xml中加入
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace:命名空间,作用为Sql隔离 --> <mapper namespace="cn.itcast.mapper.UserMapper"> <!-- 使用二级缓存 --> <cache /> |
3. 将查询的POJO实现Serializable接口
public class User implements Serializable{ private static final long serialVersionUID = -6538886943664906447L; private int id; private String username;// 用户姓名 private String sex;// 性别 private Date birthday;// 生日 private String address;// 地址 |
映射文件:
<select id="findUserByIdCache2" parameterType="int" resultType="user"> select * from User where id=#{aaa} </select> |
接口:
public User findUserByIdCache2(Integer id); |
测试代码:
@Test public void testFindUserByIdCache2() throws Exception{ SqlSession openSession = sqlSessionFactory.openSession(); //获得Mapper对象 UserMapper userMapper = openSession.getMapper(UserMapper.class); //第一次查询 User user = userMapper.findUserByIdCache2(1); System.out.println(user); openSession.close(); //第二次查询 openSession = sqlSessionFactory.openSession(); userMapper = openSession.getMapper(UserMapper.class); User user1 = userMapper.findUserByIdCache2(1); System.out.println(user1); } |
测试代码:
@Test public void testFindUserByIdCache2() throws Exception{ SqlSession openSession = sqlSessionFactory.openSession(); //获得Mapper对象 UserMapper userMapper = openSession.getMapper(UserMapper.class); //第一次查询 User user = userMapper.findUserByIdCache2(1); System.out.println(user); openSession.close(); //执行更新操作 openSession = sqlSessionFactory.openSession(); userMapper = openSession.getMapper(UserMapper.class); user.setUsername("王六"); userMapper.updateUserById(user); openSession.commit(); openSession.close(); //第二次查询 openSession = sqlSessionFactory.openSession(); userMapper = openSession.getMapper(UserMapper.class); User user1 = userMapper.findUserByIdCache2(1); System.out.println(user1); openSession.close(); //第三次查询 openSession = sqlSessionFactory.openSession(); userMapper = openSession.getMapper(UserMapper.class); User user2 = userMapper.findUserByIdCache2(1); System.out.println(user2); openSession.close(); } |
3.3 分布式缓存
1. 导入jar包
2. 添加ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore path="E:\" /> <!-- maxElementsInMemory内存中缓存的最大个数 --> <!-- maxElementsOnDisk硬盘上缓存的最大个数 --> <!-- eternal设置缓存中的数据是否永远不过期 --> <!-- overflowToDisk设置缓存中的数据是否永远不过期 --> <!-- overflowToDisk缓存数据闲置时间,超过则删除数据--> <!-- timeToIdleSeconds缓存数据闲置时间,超过则删除数据--> <!-- timeToLiveSeconds缓存数据存活时间,超过则删除数据 --> <!-- diskExpiryThreadIntervalSeconds磁盘缓存清理线程运行间隔--> <!-- memoryStoreEvictionPolicy缓存策略,最近最少使用,当缓存大小到达极限时删除最近很少使用的--> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>
|
3. 配置映射文件中使用ehcache实现
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/> |
4. 测试(同二级缓存测试)
flushCache刷新缓存:不配置默认为true
如果配置成false就是永远不刷新缓存,也就意味着缓存中的数据如果更新或者删除还有添加的时候,就成了脏数据了。
useCache是否使用缓存:如果不配置默认为true使用缓存。
如果遇到刷新,更改,删除操作频繁的情况下可以设置成false,不适用缓存,因为缓存的清空还有填充数据,也是需要耗费资源的
3.4 缓存的使用:
增加、修改、删除这样的操作很少的情况下才能使用缓存。
比如电话局的话务系统,话单的查询功能可以使用缓存。