在实际项目开发中,通常对数据库查询的性能要求很高,而MyBatis提供了查询缓存来缓存数据,从而达到提高查询性能的要求.MyBatis的查询缓存分为一级缓存和二级缓存.一级缓存是SqlSession级别的缓存,二级缓存是mapper级别的缓存,二级缓存是多个SqlSession共享的.MyBatis通过缓存机制减轻数据压力,提高数据库性能.
MyBatis的一级缓存是SqlSession级别的缓存,在操作数据库时需要构造SqlSession对象,当在同一个SqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率,需要注意的是,如果SqlSession执行了DML操作(insert,update,delete)并提交到数据库,MyBatis则会清空SqlSession中的一级缓存,这样做的目的是为了保证缓存中存储的是最新效率,避免出现脏读现象.
当一个SqlSession结束后该SqlSession中的一级缓存也就不存在了.MyBatis默认开启一级缓存,不需要进行任何配置.
示例:OneLevelCacheTest
1.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"> <mapper namespace="org.fkit.mapper.UserMapper"> <!-- 根据ID查询 --> <select id="selectUserById" parameterType="int" resultMap="userResultMap"> SELECT * FROM tb_user WHERE ID=#{id} </select> <!-- 查询所有User --> <select id="selectAllUser" resultMap="userResultMap"> SELECT * FROM tb_user </select> <!-- 根据ID删除User --> <delete id="deleteUserById" parameterType="int"> DELETE FROM tb_user WHERE id=#{id} </delete> <!-- 映射user对象的resultMap --> <resultMap type="org.fkit.domain.User" id="userResultMap"> <id property="id" column="ID" /> <result property="username" column="USERNAME" /> <result property="loginname" column="LOGINNAME" /> <result property="password" column="PASSWORD" /> <result property="phone" column="PHONE" /> <result property="address" column="ADDRESS" /> </resultMap> </mapper>
2..userMapper.java
public interface UserMapper { //根据ID查询User User selectUserById(Integer id); //查询所有User List<User> selectAllUser(); //根据ID删除User void deleteUserById(Integer id); }
3.控制器
@GetMapping("/mysql/cache/") public void cache() { //获得SqlSession实例 SqlSession sqlSession = FKSqlSessionFactory.getSqlSession(); //获得Mapper接口代理对象 UserMapper em = sqlSession.getMapper(UserMapper.class); //按ID查询 User user1 = em.selectUserById(5); User user2 = em.selectUserById(6); User user3 = em.selectUserById(5); }
4.输出
可以看出第一次查询ID=5的User对象时执行了一条select语句,但是第二次获取id为5的User对象时,并没有执行select语句.因为此时一级缓存也就是SqlSession缓存已经缓存了id=5的User对象,MyBatis直接从缓存中将对象取出来,并没有再次去数据库查询,所以第二次没有再执行select语句.
5.控制器
@GetMapping("/mysql/cache2/") public void cache2() { //获得SqlSession实例 SqlSession sqlSession = FKSqlSessionFactory.getSqlSession(); //获得Mapper接口代理对象 UserMapper em = sqlSession.getMapper(UserMapper.class); //按ID查询 User user1 = em.selectUserById(5); em.deleteUserById(5); User user2 = em.selectUserById(5); }
6.输出
在第一次查询id为5的User对象之后,执行了一个delete操作,MyBatis为了保证缓存中的是最新的信息,会清空SqlSession中的缓存,当第二次获取id为5的User对象时,一级缓存也就是SqlSession缓存中并没有缓存任何对象,所以MyBatis再次执行select语句去查询id=5的对象
由于我们没有执行
sqlSession.commit();
所以数据库仍然存在ID=5的User对象