在mybatis中,有一级缓存和二级缓存的概念:
一级缓存:一级缓存 Mybatis的一级缓存是指SQLSession,一级缓存的作用域是SQLSession, Mabits默认开启一级缓存。在同一个SqlSession中,执行相同的SQL查询时;第一次会去查询数据库,并写在缓存中,第二次会直接从缓存中取。当执行SQL时候两次查询中间发生了增删改的操作,则SQLSession的缓存会被清空。
这么设计的原因是避免读取脏数据:假设A查询了某商品库存为10件,并将10件库存的数据存入缓存中,之后被客户买走了10件,数据被delete了,但是下次查询这件商品时,并不从数据库中查询,而是从缓存中查询,就会出现错误。
二级缓存:二级缓存是mapper级别的,Mybatis默认是没有开启二级缓存的。 第一次调用mapper下的SQL去查询用户的信息,查询到的信息会存放代该mapper对应的二级缓存区域。
看概念什么的最烦了是不是?用代码看看呗:
1 package top.bigking; 2 3 import org.apache.ibatis.io.Resources; 4 import org.apache.ibatis.session.SqlSession; 5 import org.apache.ibatis.session.SqlSessionFactory; 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 7 import top.bigking.dao.DeptMapper; 8 import top.bigking.dao.UserMapper; 9 import top.bigking.pojo.Dept; 10 import top.bigking.pojo.User; 11 12 import java.io.InputStream; 13 import java.util.HashMap; 14 import java.util.List; 15 import java.util.Map; 16 17 public class mybatisStudy_start { 18 public static void main(String[] args) throws Exception{ 19 InputStream in = Resources.getResourceAsStream("mybatisStudy-config.xml"); 20 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); 21 SqlSession sqlSession = sqlSessionFactory.openSession(true);//true 表示 自动提交 22 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class); 23 List<Dept> deptList = deptMapper.query(); 24 for(Dept dept : deptList){ 25 System.out.println(dept); 26 } 27 System.out.println("-----------------------------------"); 28 //insert(deptMapper); 29 //update(deptMapper); 30 findById(deptMapper); 31 32 findById(deptMapper); 33 //delete(deptMapper); 34 //findByIdDname(deptMapper); 35 36 // UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 37 // List<User> userList = userMapper.query(); 38 // for(User user : userList) 39 // System.out.println(user); 40 sqlSession.close(); 41 42 } 43 private static void insert(DeptMapper deptMapper){ 44 Dept dept = new Dept(); 45 dept.setDeptNo(11); 46 dept.setDname("ABKing"); 47 dept.setLoc("111"); 48 int count = deptMapper.insert(dept); 49 System.out.println(count); 50 } 51 public static void update(DeptMapper deptMapper){ 52 Dept dept = new Dept(); 53 dept.setDeptNo(11); 54 dept.setDname("ABKing"); 55 dept.setLoc("上海"); 56 int count = deptMapper.update(dept); 57 System.out.println(count); 58 } 59 public static void findById(DeptMapper deptMapper){ 60 Dept dept = deptMapper.findById(11); 61 System.out.println(dept); 62 } 63 public static void delete(DeptMapper deptMapper){ 64 int count = deptMapper.delete(11); 65 System.out.println(count); 66 } 67 public static void findByIdDname(DeptMapper deptMapper){ 68 Map map = new HashMap(); 69 map.put("deptNo", "11"); 70 map.put("dname", "ABKing"); 71 Dept dept = deptMapper.findByIdDname(map); 72 System.out.println(dept); 73 } 74 }
看30行和32行,能看到调用了两次findById(deptMapper),运行,查看控制台的日志(需要log4j包)
DEBUG [main] - ==> Preparing: select deptNo, dname, loc from Dept where deptNo=?
只打印出了一条SQL语句
而如果我们在31行加入sqlSession.clearCache();
1 package top.bigking; 2 3 import org.apache.ibatis.io.Resources; 4 import org.apache.ibatis.session.SqlSession; 5 import org.apache.ibatis.session.SqlSessionFactory; 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 7 import top.bigking.dao.DeptMapper; 8 import top.bigking.dao.UserMapper; 9 import top.bigking.pojo.Dept; 10 import top.bigking.pojo.User; 11 12 import java.io.InputStream; 13 import java.util.HashMap; 14 import java.util.List; 15 import java.util.Map; 16 17 public class mybatisStudy_start { 18 public static void main(String[] args) throws Exception{ 19 InputStream in = Resources.getResourceAsStream("mybatisStudy-config.xml"); 20 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); 21 SqlSession sqlSession = sqlSessionFactory.openSession(true);//true 表示 自动提交 22 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class); 23 List<Dept> deptList = deptMapper.query(); 24 for(Dept dept : deptList){ 25 System.out.println(dept); 26 } 27 System.out.println("-----------------------------------"); 28 //insert(deptMapper); 29 //update(deptMapper); 30 findById(deptMapper); 31 sqlSession.clearCache(); 32 findById(deptMapper); 33 //delete(deptMapper); 34 //findByIdDname(deptMapper); 35 36 // UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 37 // List<User> userList = userMapper.query(); 38 // for(User user : userList) 39 // System.out.println(user); 40 sqlSession.close(); 41 42 } 43 private static void insert(DeptMapper deptMapper){ 44 Dept dept = new Dept(); 45 dept.setDeptNo(11); 46 dept.setDname("ABKing"); 47 dept.setLoc("111"); 48 int count = deptMapper.insert(dept); 49 System.out.println(count); 50 } 51 public static void update(DeptMapper deptMapper){ 52 Dept dept = new Dept(); 53 dept.setDeptNo(11); 54 dept.setDname("ABKing"); 55 dept.setLoc("上海"); 56 int count = deptMapper.update(dept); 57 System.out.println(count); 58 } 59 public static void findById(DeptMapper deptMapper){ 60 Dept dept = deptMapper.findById(11); 61 System.out.println(dept); 62 } 63 public static void delete(DeptMapper deptMapper){ 64 int count = deptMapper.delete(11); 65 System.out.println(count); 66 } 67 public static void findByIdDname(DeptMapper deptMapper){ 68 Map map = new HashMap(); 69 map.put("deptNo", "11"); 70 map.put("dname", "ABKing"); 71 Dept dept = deptMapper.findByIdDname(map); 72 System.out.println(dept); 73 } 74 }
此时查看控制台的日志
DEBUG [main] - ==> Preparing: select deptNo, dname, loc from Dept where deptNo=? DEBUG [main] - ==> Parameters: 11(Integer) DEBUG [main] - <== Total: 1 Dept{deptNo=11, dname='ABKing', loc='111'} DEBUG [main] - ==> Preparing: select deptNo, dname, loc from Dept where deptNo=?
可以看到打印出了两条SQL语句,这足以证明,使用了sqlSession.clearCache();之后,缓存被清空了
接下来证明二级缓存:
应当明确的是,二级缓存是mapper级别的缓存,使用同一个Mapper.class的的Mapper类和SqlSession类都共用同一个二级缓存
代码如下:
1 package top.bigking; 2 3 import org.apache.ibatis.io.Resources; 4 import org.apache.ibatis.session.SqlSession; 5 import org.apache.ibatis.session.SqlSessionFactory; 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 7 import top.bigking.dao.DeptMapper; 8 import top.bigking.dao.UserMapper; 9 import top.bigking.pojo.Dept; 10 import top.bigking.pojo.User; 11 12 import java.io.InputStream; 13 import java.util.HashMap; 14 import java.util.List; 15 import java.util.Map; 16 17 public class mybatisStudy_start { 18 public static void main(String[] args) throws Exception{ 19 InputStream in = Resources.getResourceAsStream("mybatisStudy-config.xml"); 20 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); 21 SqlSession sqlSession = sqlSessionFactory.openSession(true);//true 表示 自动提交 22 SqlSession sqlSession1 = sqlSessionFactory.openSession(true); 23 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class); 24 DeptMapper deptMapper1 = sqlSession1.getMapper(DeptMapper.class); 25 List<Dept> deptList = deptMapper.query(); 26 for(Dept dept : deptList){ 27 System.out.println(dept); 28 } 29 System.out.println("-----------------------------------"); 30 //insert(deptMapper); 31 //update(deptMapper); 32 findById(deptMapper); 33 sqlSession.close(); 34 //sqlSession.clearCache(); 35 findById(deptMapper1); 36 sqlSession1.close(); 37 //delete(deptMapper); 38 //findByIdDname(deptMapper); 39 40 // UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 41 // List<User> userList = userMapper.query(); 42 // for(User user : userList) 43 // System.out.println(user); 44 //sqlSession.close(); 45 46 } 47 private static void insert(DeptMapper deptMapper){ 48 Dept dept = new Dept(); 49 dept.setDeptNo(11); 50 dept.setDname("ABKing"); 51 dept.setLoc("111"); 52 int count = deptMapper.insert(dept); 53 System.out.println(count); 54 } 55 public static void update(DeptMapper deptMapper){ 56 Dept dept = new Dept(); 57 dept.setDeptNo(11); 58 dept.setDname("ABKing"); 59 dept.setLoc("上海"); 60 int count = deptMapper.update(dept); 61 System.out.println(count); 62 } 63 public static void findById(DeptMapper deptMapper){ 64 Dept dept = deptMapper.findById(11); 65 System.out.println(dept); 66 } 67 public static void delete(DeptMapper deptMapper){ 68 int count = deptMapper.delete(11); 69 System.out.println(count); 70 } 71 public static void findByIdDname(DeptMapper deptMapper){ 72 Map map = new HashMap(); 73 map.put("deptNo", "11"); 74 map.put("dname", "ABKing"); 75 Dept dept = deptMapper.findByIdDname(map); 76 System.out.println(dept); 77 } 78 }
在DeptMapper.xml中
<select id="findById" resultType="Dept" useCache="true"> select deptNo, dname, loc from Dept where deptNo=#{deptNo} </select>
通过useCache可以使用二级缓存
在mybatisStudy-config.xml中,在properties标签下,添加
<settings> <setting name="cacheEnabled" value="true"/> </settings>
这是全局设置,表示开启二级缓存
查看控制台输出的日志:
DEBUG [main] - ==> Preparing: select deptNo, dname, loc from Dept where deptNo=? DEBUG [main] - ==> Parameters: 11(Integer) DEBUG [main] - <== Total: 1 Dept{deptNo=11, dname='ABKing', loc='111'} DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@7a9273a8]
可以看到,由于使用了二级缓存,我们的日志中,只出现了一条SQLQL语句
而如果我们把DeptMapper.xml中的代码改为:
<select id="findById" resultType="Dept" useCache="false"> select deptNo, dname, loc from Dept where deptNo=#{deptNo} </select>
表示不使用二级缓存
运行,查看控制台:
DEBUG [main] - ==> Preparing: select deptNo, dname, loc from Dept where deptNo=? DEBUG [main] - ==> Parameters: 11(Integer) DEBUG [main] - <== Total: 1 Dept{deptNo=11, dname='ABKing', loc='111'} DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@7a9273a8] DEBUG [main] - Returned connection 2056418216 to pool. DEBUG [main] - Opening JDBC Connection DEBUG [main] - Checked out connection 2056418216 from pool. DEBUG [main] - ==> Preparing: select deptNo, dname, loc from Dept where deptNo=? DEBUG [main] - ==> Parameters: 11(Integer) DEBUG [main] - <== Total: 1 Dept{deptNo=11, dname='ABKing', loc='111'} DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@7a9273a8]
可以看到两条SQL语句
可是我们的代码中,并没有使用到清空一级缓存的函数sqlSession.clearCache();
由此可证明,这里是二级缓存的开关
参考:
https://m.w3cschool.cn/kzsow/kzsow-qmod2gri.html
https://www.cnblogs.com/happyflyingpig/p/7739749.html
https://www.cnblogs.com/yuluoxingkong/p/8205858.html
https://www.cnblogs.com/charlypage/p/9747145.html
----------------------------------------------------------------------------
大家好,我是ABKing
金麟岂是池中物,一遇风云便化龙!
欢迎与我交流技术问题