1.理解mybatis的缓存
如大部分的持久化框架,mybatis也提供了一级缓存与二级缓存。
一级缓存:基于perpetualcache的hashmap本地缓存,其存储作用为session,当session进行flush或者close之后,将该session中的cache进行清空。
二级缓存:机制与一级缓存类似,默认采用perpetualcache,hashmap存储,不同在于存储作用域为Mapper(namespace),并且可以自定义存储。
对于存储数据更新机制,当某一个作用域进行了C/U/D之后,默认该作用域下所有select中的缓存将被clear。
一:一级缓存
1.需求,目录结构
根据id查询对应的用户记录对象。
2.准备数据
1 CREATE TABLE c_user( 2 id INT PRIMARY KEY auto_increment, 3 name VARCHAR(20), 4 age INT 5 ); 6 INSERT INTO c_user(name,age) VALUES("TOM",12); 7 INSERT INTO c_user(NAME,age) VALUES("BOB",18);
3.创建实体类
1 package com.cao.bean; 2 3 public class CUser { 4 private int id; 5 private String name; 6 private int age; 7 public CUser() {} 8 public CUser(int id,String name,int age) { 9 this.id=id; 10 this.name=name; 11 this.age=age; 12 } 13 public int getId() { 14 return id; 15 } 16 public void setId(int id) { 17 this.id = id; 18 } 19 public String getName() { 20 return name; 21 } 22 public void setName(String name) { 23 this.name = name; 24 } 25 public int getAge() { 26 return age; 27 } 28 public void setSex(int age) { 29 this.age = age; 30 } 31 @Override 32 public String toString() { 33 return "CUser [id=" + id + ", name=" + name + ", age=" + age + "]"; 34 } 35 36 37 }
4.映射文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="procedure"> 6 <select id="getUser" parameterType="int" resultType="com.cao.bean.CUser"> 7 select * from c_user where id=#{id} 8 </select> 9 <update id="updateUser" parameterType="com.cao.bean.CUser"> 10 update c_user set 11 name=#{name},age=#{age} where id=#{id} 12 </update> 13 </mapper>
5.配置文件
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> 3 4 <configuration> 5 <environments default="development"> 6 <environment id="development"> 7 <transactionManager type="JDBC"> 8 <property name="" value=""/> 9 </transactionManager> 10 <dataSource type="UNPOOLED"> 11 <property name="driver" value="com.mysql.jdbc.Driver"/> 12 <property name="url" value="jdbc:mysql://127.0.0.1:3308/mybatis"/> 13 <property name="username" value="root"/> 14 <property name="password" value="123456"/> 15 </dataSource> 16 </environment> 17 </environments> 18 19 <mappers> 20 <mapper resource="com/jun/sql/config/user.xml"/> 21 </mappers> 22 23 </configuration>
6.测试类
1 package com.jun.main; 2 3 import java.io.IOException; 4 import java.io.Reader; 5 import java.util.HashMap; 6 import java.util.Map; 7 8 import org.apache.ibatis.io.Resources; 9 import org.apache.ibatis.session.SqlSession; 10 import org.apache.ibatis.session.SqlSessionFactory; 11 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 12 import org.junit.Test; 13 14 import com.cao.bean.CUser; 15 public class MainTest { 16 /** 17 * 方式一 18 * @throws Exception 19 */ 20 @Test 21 public void test1() throws Exception { 22 Reader reader=Resources.getResourceAsReader("com/cao/config/Configuration.xml"); 23 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader); 24 SqlSession sqlSession=sqlSessionFactory.openSession(true); //true后是自动提交 25 26 String statement="procedure.getUser"; 27 28 CUser cuser=sqlSession.selectOne(statement, 1); 29 System.out.println(cuser); 30 //再跑一次 31 cuser=sqlSession.selectOne(statement, 1); 32 System.out.println(cuser); 33 sqlSession.close(); 34 } 35 36 37 }
7.效果
说明一级缓存是开着的。
8.调用方法进行清空缓存
sqlSession.clearCache();
1 package com.jun.main; 2 3 import java.io.IOException; 4 import java.io.Reader; 5 import java.util.HashMap; 6 import java.util.Map; 7 8 import org.apache.ibatis.io.Resources; 9 import org.apache.ibatis.session.SqlSession; 10 import org.apache.ibatis.session.SqlSessionFactory; 11 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 12 import org.junit.Test; 13 14 import com.cao.bean.CUser; 15 public class MainTest { 16 /** 17 * 方式一 18 * @throws Exception 19 */ 20 @Test 21 public void test1() throws Exception { 22 Reader reader=Resources.getResourceAsReader("com/cao/config/Configuration.xml"); 23 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader); 24 SqlSession sqlSession=sqlSessionFactory.openSession(true); //true后是自动提交 25 26 String statement="procedure.getUser"; 27 28 CUser cuser=sqlSession.selectOne(statement, 1); 29 System.out.println(cuser); 30 //再跑一次 31 cuser=sqlSession.selectOne(statement, 1); 32 System.out.println(cuser); 33 //清空缓存 34 sqlSession.clearCache(); 35 cuser=sqlSession.selectOne(statement, 1); 36 System.out.println(cuser); 37 38 sqlSession.close(); 39 } 40 41 42 }
9.效果
10.增删改后清空缓存
1 package com.jun.main; 2 3 import java.io.IOException; 4 import java.io.Reader; 5 import java.util.HashMap; 6 import java.util.Map; 7 8 import org.apache.ibatis.io.Resources; 9 import org.apache.ibatis.session.SqlSession; 10 import org.apache.ibatis.session.SqlSessionFactory; 11 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 12 import org.junit.Test; 13 14 import com.cao.bean.CUser; 15 public class MainTest { 16 /** 17 * 方式一 18 * @throws Exception 19 */ 20 @Test 21 public void test1() throws Exception { 22 Reader reader=Resources.getResourceAsReader("com/cao/config/Configuration.xml"); 23 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader); 24 SqlSession sqlSession=sqlSessionFactory.openSession(true); //true后是自动提交 25 26 String statement="procedure.getUser"; 27 28 CUser cuser=sqlSession.selectOne(statement, 1); 29 System.out.println(cuser); 30 //再跑一次 31 cuser=sqlSession.selectOne(statement, 1); 32 System.out.println(cuser); 33 //清空缓存 34 // sqlSession.clearCache(); 35 //执行增删改操作 36 String statement2="procedure.updateUser"; 37 int update=sqlSession.update(statement2, new CUser(1,"JACK",15)); 38 sqlSession.commit(); 39 System.out.println(update); 40 //再次查询 41 cuser=sqlSession.selectOne(statement, 1); 42 System.out.println(cuser); 43 44 sqlSession.close(); 45 } 46 47 48 }
11.效果
12.关闭session清空缓存
二:二级缓存
1.添加一个<>cache>在映射文件中
<cache/>
2.新建对象(这个对象必须实现序列化接口Serializable)
注意点。
1 package com.cao.bean; 2 3 import java.io.Serializable; 4 5 public class CUser implements Serializable{ 6 private int id; 7 private String name; 8 private int age; 9 public CUser() {} 10 public CUser(int id,String name,int age) { 11 this.id=id; 12 this.name=name; 13 this.age=age; 14 } 15 public int getId() { 16 return id; 17 } 18 public void setId(int id) { 19 this.id = id; 20 } 21 public String getName() { 22 return name; 23 } 24 public void setName(String name) { 25 this.name = name; 26 } 27 public int getAge() { 28 return age; 29 } 30 public void setSex(int age) { 31 this.age = age; 32 } 33 @Override 34 public String toString() { 35 return "CUser [id=" + id + ", name=" + name + ", age=" + age + "]"; 36 } 37 38 39 }
3.在映射文件中加一个cache标签
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="procedure"> 6 <cache></cache> 7 <select id="getUser" parameterType="int" resultType="com.cao.bean.CUser"> 8 select * from c_user where id=#{id} 9 </select> 10 <update id="updateUser" parameterType="com.cao.bean.CUser"> 11 update c_user set 12 name=#{name},age=#{age} where id=#{id} 13 </update> 14 </mapper>
4.测试类
1 package com.jun.main; 2 3 import java.io.IOException; 4 import java.io.Reader; 5 import java.util.HashMap; 6 import java.util.Map; 7 8 import org.apache.ibatis.io.Resources; 9 import org.apache.ibatis.session.SqlSession; 10 import org.apache.ibatis.session.SqlSessionFactory; 11 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 12 import org.junit.Test; 13 14 import com.cao.bean.CUser; 15 public class MainTest { 16 /** 17 * 一 18 * @throws Exception 19 */ 20 @Test 21 public void test1() throws Exception { 22 Reader reader=Resources.getResourceAsReader("com/cao/config/Configuration.xml"); 23 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader); 24 SqlSession sqlSession=sqlSessionFactory.openSession(true); //true后是自动提交 25 26 String statement="procedure.getUser"; 27 28 CUser cuser=sqlSession.selectOne(statement, 1); 29 System.out.println(cuser); 30 //再跑一次 31 cuser=sqlSession.selectOne(statement, 1); 32 System.out.println(cuser); 33 //清空缓存 34 // sqlSession.clearCache(); 35 //执行增删改操作 36 String statement2="procedure.updateUser"; 37 int update=sqlSession.update(statement2, new CUser(1,"JACK",15)); 38 sqlSession.commit(); 39 System.out.println(update); 40 //再次查询 41 cuser=sqlSession.selectOne(statement, 1); 42 System.out.println(cuser); 43 44 sqlSession.close(); 45 } 46 /** 47 * 二 48 * @throws Exception 49 */ 50 @Test 51 public void test2() throws Exception { 52 Reader reader=Resources.getResourceAsReader("com/cao/config/Configuration.xml"); 53 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader); 54 SqlSession sqlSession1=sqlSessionFactory.openSession(); 55 SqlSession sqlSession2=sqlSessionFactory.openSession(); 56 57 String statement="procedure.getUser"; 58 59 CUser cuser=sqlSession1.selectOne(statement, 1); 60 sqlSession1.commit(); 61 System.out.println(cuser); 62 //再跑一次 63 cuser=sqlSession2.selectOne(statement, 1); 64 sqlSession1.commit(); 65 System.out.println(cuser); 66 67 68 sqlSession1.close(); 69 } 70 71 72 }
5.效果
6.注意点
如果第一个session没有提交,则没有进行二级缓存。
当然,如果第一个session是自动提交,第二个session也没有进行二次缓存。
所以,想实现二级缓存,需要前面的session已经提交过,并且相同的提交sql。
三:回收策略
1.策略
LRU:最近最少使用,移除长时间不使用的对象
FIFO:先进先出
SOFT:软引用,移除基于垃圾回收状态和软引用规则的对象
WEAK:弱引用,更积极的移除基于垃圾收集器状态和软引用规则的对象
2.默认
LRU。