MyBatis (d) - a cache and secondary cache

  • Description: Like most of persistence frameworks, Mybatis also provides a caching strategy to reduce the number of database queries by caching strategies to improve performance.

Cache

  • Cache prove the existence of
    a cache is SqlSession level cache, as long as SqlSession no flush or close, it exists.
  • Writing User Interface persistence layer Dao
public interface IUserDao {
	/**
	* 根据 id 查询
	* @param userId
	* @return
	*/
	User findById(Integer userId);
}
  • Writing User persistence layer mapping file
<?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="com.itheima.dao.IUserDao">
	<!-- 根据 id 查询 --> 
	<select id="findById" resultType="UsEr" parameterType="int" useCache="true">
		select * from user where id = #{uid}
	</select>
</mapper>
  • Writing Test Methods
public class UserTest {
	private InputStream in ;
	private SqlSessionFactory factory;
	private SqlSession session;
	private IUserDao userDao;
	
	@Test
	public void testFindById() {
		//6.执行操作
		User user = userDao.findById(41);
		System.out.println("第一次查询的用户:"+user);
		User user2 = userDao.findById(41);
		System.out.println("第二次查询用户:"+user2);
		System.out.println(user == user2);
	}
	
	@Before
	//在测试方法执行之前执行
	public void init()throws Exception {
		//1.读取配置文件
		in = Resources.getResourceAsStream("SqlMapConfig.xml");
		//2.创建构建者对象
		SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
		//3.创建 SqlSession 工厂对象
		factory = builder.build(in);
		//4.创建 SqlSession 对象
		session = factory.openSession();
		//5.创建 Dao 的代理对象
		userDao = session.getMapper(IUserDao.class);
	}
	
	@After
	//在测试方法执行完成之后执行
	public void destroy() throws Exception{
		//7.释放资源
		session.close();
		in.close();
	} 
}

Test results are as follows:
Here Insert Picture Description

  • We can see that although in the above code, we query twice, but in the end only the implementation of a database operation, which is available to us Mybatis level cache working. Because the presence of a buffer, the second query result in the id of the record 41, and does not issue sql statement data from a database query, but a query from the cache.
  • Cache analysis of
    a cache is a cache SqlSession range, when you call to modify the SqlSession, add, delete, commit (), close () method, etc., it will empty the cache.
    Here Insert Picture Description
  • Testing a cache cleared
	/**
	* 测试一级缓存
	*/
	@Test
	public void testFirstLevelCache(){
		User user1 = userDao.findById(41);
		System.out.println(user1);
		
		sqlSession.clearCache();//此方法也可以清空缓存

		userDao = sqlSession.getMapper(IUserDao.class);
		User user2 = userDao.findById(41);
		System.out.println(user2);
		System.out.println(user1 == user2);
	}
	/**
	* 测试缓存的同步
	*/
	@Test
	public void testClearlCache(){
		//1.根据 id 查询用户
		User user1 = userDao.findById(41);
		System.out.println(user1);
		//2.更新用户信息
		user1.setUsername("update user clear cache");
		user1.setAddress("北京市海淀区");
		userDao.updateUser(user1);
		//3.再次查询 id 为 41 的用户
		User user2 = userDao.findById(41);
		System.out.println(user2);
		System.out.println(user1 == user2);
	}
当执行sqlSession.close()后,再次获取sqlSession并查询id=41的User对象时,又重新执行了sql 
语句,从数据库进行了查询操作。

Mybatis secondary cache

A mapper mapping the secondary cache level cache, a plurality SqlSession sql statement to operate the same Mapper maps, can share SqlSession plurality of secondary cache, the secondary cache across the SqlSession.

  • Secondary cache configuration diagram of
    Here Insert Picture Description
    first turns of the secondary cache mybatis.
    sqlSession1 to query the user information, query the user information query data will be stored in the secondary cache.
    If the same data to perform SqlSession3 mapper maps the sql, commit the execution, it will clear the secondary cache area of the mapper mapping.
    sqlSession2 sqlSession1 to query the same user information, will first find whether there is data to the cache, if there is data taken directly from the cache.
Secondary cache on and off
  • The first step: Turn on the secondary cache files in SqlMapConfig.xml
<settings>
	<!-- 开启二级缓存的支持 --> 
	<setting name="cacheEnabled" value="true"/>
</settings>
因为 cacheEnabled 取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;false 代表不开启二级缓存。
  • Step Two: Configure related Mapper mapping file
<cache>标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace值。

<?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="com.itheima.dao.IUserDao">
		<!-- 开启二级缓存的支持 -->
		<cache></cache>
	</mapper>
  • The third step: The above statement configuration attributes useCache
<!-- 根据 id 查询 --> 
<select id="findById" resultType="user" parameterType="int" useCache="true">
	select * from user where id = #{uid}
</select> 
	将 UserDao.xml 映射文件中的<select>标签中设置 useCache=true”代表当前这个 
statement 要使用二级缓存,如果不使用二级缓存可以设置为 false
注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。
  • Secondary cache test
public class SecondLevelCacheTest {
private InputStream in;
private SqlSessionFactory factory; @Before//用于在测试方法执行之前执行
public void init()throws Exception{
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.获取 SqlSessionFactory
factory = new SqlSessionFactoryBuilder().build(in);
}@After//用于在测试方法执行之后执行
public void destroy()throws Exception{
in.close();
}
/**
* 测试一级缓存
*/
@Test
public void testFirstLevelCache(){
	SqlSession sqlSession1 = factory.openSession();
	IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);
	User user1 = dao1.findById(41);
	System.out.println(user1);
	sqlSession1.close();//一级缓存消失
	
	SqlSession sqlSession2 = factory.openSession();
	IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);
	User user2 = dao2.findById(41);
	System.out.println(user2);
	sqlSession2.close();
	System.out.println(user1 == user2);
	}
}

After the above tests, we found that the implementation of the two inquiries, and after performing the first query, we closed the first-level cache, go to perform a second query, we found no sql statement issued to the database, so this the data can only be derived from what we call secondary cache.

  • Secondary cache Notes
	当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,
这种就可以使用序列化
方式来保存对象。
public class User implements Serializable {
	private Integer id;
	private String username;
	private Date birthday;
	private String sex;
	private String address; 
} 
Published 58 original articles · won praise 7 · views 9247

Guess you like

Origin blog.csdn.net/Mr_OO/article/details/102573733