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);
}