什麼是緩存?
存在於內存中的臨時數據
爲什麼使用緩存?
可以減少和數據庫交互的次數,提高執行效率
什麼樣的數據能使用緩存?
適用於緩存 經常查詢,並且不經常改變。數據的正確與否對最終結果影響不大的
不適用於緩存 經常改變的數據,以及數據的正確與否對最終結果影響很大。例如:商品的庫存,銀行的匯率,股市的股價
mybatis中的一級緩存和二級緩存
一級緩存
指的是mybatis中Sqlsession對象的緩存,當我們執行查詢之後,查詢的結果會同時存入到sqlsession爲我們提供的一塊區域中,該區域的結構是一個map,當我們再次查詢同樣的數據,mybatis會先去sqlsession中查詢是否有,有的話直接拿出來用。當sqlsession對象消失時,mybatis的一級緩存就消失了
public class MybatisTest {
private InputStream in;
private SqlSession sqlSession;
private SqlSessionFactory factory;
private IUserDao userDao;
@Before//用於在測試方法執行之前執行
public void init() throws Exception{
in = Resources.getResourceAsStream("SqlMapConfig.xml");
factory = new SqlSessionFactoryBuilder().build(in);
//創建sqlsession時傳遞一個true參數則會自動提交事物
sqlSession = factory.openSession(true);
userDao = sqlSession.getMapper(IUserDao.class);
}
@After//用於在測試方法執行之後執行
public void destory() throws Exception{
//提交事物
//sqlSession.commit();
sqlSession.close();
in.close();
}
@Test
public void testFirstLevelCache(){
User user1 = userDao.findById(41);
System.out.println(user1);
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
}
可以從執行結果中發現,只執行了一次查詢。而且產生的兩個對象是同一個。第二次就是從緩存中查詢的
/**
* 關閉sqlSession並重新打開
*/
@Test
public void testFirstLevelCache(){
User user1 = userDao.findById(41);
System.out.println(user1);
// sqlSession.close()
//此方法也可以清空緩存
sqlSession.clearCache();;
//再次開啓sqlsession對象
sqlSession = factory.openSession();
userDao = sqlSession.getMapper(IUserDao.class);
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user1 == user2);
}
可以發現,執行了兩次查詢。而且兩次查詢的對象不是同一個,可以看出,將sqlsession關閉之後,緩存就消失了。
一級緩存是 SqlSession 範圍的緩存,當調用 SqlSession 的修改,添加,刪除,commit(),close()等方法時,就會清空一級緩存。
@Test
public void testClearCache(){
//1.根據id查詢用戶
User user1 = userDao.findById(41);
System.out.println(user1);
//2.更新用戶信息
user1.setUsername("uucc");
user1.setAddress("北京市海淀區");
userDao.updateUser(user1);
//3.再次查詢id爲41的用戶
User user2 = userDao.findById(41);
System.out.println(user2);
System.out.println(user2 == user1);
}
第一次發起查詢用戶 id 爲 1 的用戶信息,先去找緩存中是否有 id 爲 1 的用戶信息,如果沒有,從數據庫查
詢用戶信息。得到用戶信息,將用戶信息存儲到一級緩存中。
如果 sqlSession 去執行 commit 操作(執行插入、更新、刪除),清空 SqlSession 中的一級緩存,這樣
做的目的爲了讓緩存中存儲的是最新的信息,避免髒讀。
第二次發起查詢用戶 id 爲 1 的用戶信息,先去找緩存中是否有 id 爲 1 的用戶信息,緩存中有,直接從緩存
中獲取用戶信息。
二級緩存
它指定是Mybatis中SqlSessionFactory對象的緩存,由同一個SqlSessionFactory對象創建的SqlSession共享其緩存
二級緩存的使用步驟:
第一步,讓mybatis框架支持二級緩存(在SqlMapConfig.xml中配置)
<!-- 全局的開啓配置文件中的所有已經配置的任何緩存 -->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
第二步,讓當前的映射文件支持二級緩存(在IUserDao.xml中配置)
<!-- 開啓user支持二級緩存 -->
<cache/>
第三步:讓當前的操作支持二級緩存(在select標籤中配置)
<!-- 根據id查詢用戶 -->
<select id="findById" parameterType="INT" resultType="com.echo.domain.User" useCache="true">
select * from user where id = #{id}
</select>
測試
@Test
public void testFirstLevelCache(){
SqlSession sqlSession1 = factory.openSession();
IUserDao iUserDao1 = sqlSession1.getMapper(IUserDao.class);
User user1 = iUserDao1.findById(41);
System.out.println(user1);
//一級緩存消失
sqlSession1.close();
SqlSession sqlSession2 = factory.openSession();
IUserDao iUserDao2 = sqlSession2.getMapper(IUserDao.class);
User user2 = iUserDao2.findById(41);
System.out.println(user1);
sqlSession2.close();
System.out.println(user1 == user2);
}
結果
最後打印爲false原因是二級緩存中存放的是數據而不是對象
在二級緩存中存放的是諸如
{“id”:41,“username”:“老王”,“address”:“北京”}類型的數據
誰用時就將數據拿過來,之後創建一個新的用戶,將數據填充到新的用戶對象中