MyBatis快取之一級快取
阿新 • • 發佈:2018-12-09
1 快取物件
不跨session:
package com.rl.test; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import com.rl.model1.Person; public class MyBatisTest10 { SqlSessionFactory sqlSessionFactory; @Before public void setUp() throws Exception { InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); } @Test public void test() { SqlSession sqlSession = sqlSessionFactory.openSession(); //發出sql語句 Person person1 = sqlSession.selectOne("com.rl.mapper.PersonMapper.selectPersonById", 1); //不發出sql語句, 直接在快取中查詢 Person person2 = sqlSession.selectOne("com.rl.mapper.PersonMapper.selectPersonById", 1); System.out.println(person1); System.out.println(person2); } }
跨session:
@Test public void test1() { SqlSession sqlSession = sqlSessionFactory.openSession(); //發出sql語句 sqlSession.selectOne("com.rl.mapper.PersonMapper.selectPersonById", 1); sqlSession.close(); SqlSession sqlSession2 = sqlSessionFactory.openSession(); //再次發出sql語句 sqlSession2.selectOne("com.rl.mapper.PersonMapper.selectPersonById", 1); sqlSession2.close(); }
以上例子說明MyBatis的一級快取是不能跨session的, 一旦跨session了, 則必須重新發出sql語句查詢資料庫
另外, 一級快取有個特點, 就是不受配置, 都是MyBatis自己管理, 我們只負責用
2 快取集合
@Test public void test2() { SqlSession sqlSession = sqlSessionFactory.openSession(); //發出sql語句 List<Person> pList1 = sqlSession.selectList("selectPersonAll"); //不發出sql語句 List<Person> pList2 = sqlSession.selectList("selectPersonAll"); for(Person p: pList1){ System.out.println(p); } for(Person p: pList2){ System.out.println(p); } }
假如在這個查詢的過程中後臺的資料被手動修改了, 此時快取是無法得知的, 依然會輸出快取中的內容
如果是程式修改的後臺資料, 則MyBatis是能夠感知到, 因為涉及到了快取重新整理
1 在查詢物件時修改資料:
@Test
public void test3() {
SqlSession sqlSession = sqlSessionFactory.openSession();
//發出sql語句
Person p = sqlSession.selectOne("com.rl.mapper.PersonMapper.selectPersonById", 1);
p.setName("火星");
sqlSession.update("com.rl.mapper.PersonMapper.dynamicUpdate", p);
sqlSession.commit();
//重新發出sql語句
Person p1 = sqlSession.selectOne("com.rl.mapper.PersonMapper.selectPersonById", 1);
//兩次輸出的都是新的資料
System.out.println(p);
System.out.println(p1);
}
由於update了資料庫, MyBatis將快取中的資料全部清空, 所以第二次查詢時必須要重新發出sql語句, 並且輸出的都是新的資料
2 在查詢集合時修改資料:
測試程式碼:
@Test
public void test4() {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Person> pList1 = sqlSession.selectList("selectPersonAll");
Person person = new Person();
person.setName("王五");
person.setGender(2);
person.setBirthday(new Date());
person.setPersonAddr("紐約");
sqlSession.insert("com.rl.mapper.PersonMapper.insert", person);
sqlSession.commit();
List<Person> pList2 = sqlSession.selectList("selectPersonAll");
//輸出的依舊是原先的資料
for(Person p: pList1){
System.out.println(p);
}
//輸出的是最新的資料
for(Person p: pList2){
System.out.println(p);
}
}
結果輸出:
Person [personId=1, name=海地, gender=1, personAddr=天津, birthday=Fri Sep 07 00:00:00 CST 2018, orderList=null]
Person [personId=2, name=晁蓋, gender=2, personAddr=上海, birthday=Mon Sep 10 00:00:00 CST 2018, orderList=null]
Person [personId=4, name=黃忠, gender=1, personAddr=上海, birthday=Sun Sep 09 00:00:00 CST 2018, orderList=null]
Person [personId=1, name=海地, gender=1, personAddr=天津, birthday=Fri Sep 07 00:00:00 CST 2018, orderList=null]
Person [personId=2, name=晁蓋, gender=2, personAddr=上海, birthday=Mon Sep 10 00:00:00 CST 2018, orderList=null]
Person [personId=4, name=黃忠, gender=1, personAddr=上海, birthday=Sun Sep 09 00:00:00 CST 2018, orderList=null]
Person [personId=4000025, name=王五, gender=2, personAddr=紐約, birthday=Tue Sep 11 00:00:00 CST 2018, orderList=null]
但是快取集合跟快取物件有所不同, 快取物件時, 快取一旦修改後被清空, 則原先查詢上來的資料也會同步地修改了, 但是快取集合卻不會, 也就是上面輸出時還是原先的資料, 只有第二次查詢集合時才是最新的資料
3 在查詢時刪除資料:
對於集合的情況跟插入新資料一樣:
測試程式碼:
@Test
public void test5() {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Person> pList1 = sqlSession.selectList("selectPersonAll");
Person person = sqlSession.selectOne("com.rl.mapper.PersonMapper.selectPersonById", 1);
sqlSession.delete("com.rl.mapper.PersonMapper.delete", person);
sqlSession.commit();
List<Person> pList2 = sqlSession.selectList("selectPersonAll");
for(Person p: pList1){
System.out.println(p);
}
for(Person p: pList2){
System.out.println(p);
}
}
輸出結果:
Person [personId=1, name=海地, gender=1, personAddr=天津, birthday=Fri Sep 07 00:00:00 CST 2018, orderList=null]
Person [personId=2, name=晁蓋, gender=2, personAddr=上海, birthday=Mon Sep 10 00:00:00 CST 2018, orderList=null]
Person [personId=4, name=黃忠, gender=1, personAddr=上海, birthday=Sun Sep 09 00:00:00 CST 2018, orderList=null]
Person [personId=4000025, name=王五, gender=2, personAddr=紐約, birthday=Tue Sep 11 00:00:00 CST 2018, orderList=null]
Person [personId=2, name=晁蓋, gender=2, personAddr=上海, birthday=Mon Sep 10 00:00:00 CST 2018, orderList=null]
Person [personId=4, name=黃忠, gender=1, personAddr=上海, birthday=Sun Sep 09 00:00:00 CST 2018, orderList=null]
Person [personId=4000025, name=王五, gender=2, personAddr=紐約, birthday=Tue Sep 11 00:00:00 CST 2018, orderList=null]
對於查詢物件時將資料刪除的情況則略有不同:
@Test
public void test6() {
SqlSession sqlSession = sqlSessionFactory.openSession();
Person person1 = sqlSession.selectOne("com.rl.mapper.PersonMapper.selectPersonById", 2);
Person person = sqlSession.selectOne("com.rl.mapper.PersonMapper.selectPersonById", 2);
sqlSession.delete("com.rl.mapper.PersonMapper.delete", person);
sqlSession.commit();
Person person2 = sqlSession.selectOne("com.rl.mapper.PersonMapper.selectPersonById", 2);
//還是能夠輸出已經被刪除的資料
System.out.println(person1);
//輸出null
System.out.println(person2);
}