MyBatis缓存之一级缓存

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

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值