MyBatis缓存

MyBatis

Mybatis笔记连载上篇连接Mybatis简单操作学习

Mybatis笔记连载下篇连接Mybatis动态SQL

一、自带缓存

MyBatis在默认会开启一级缓存,一级是在SqlSession层进行缓存的,即同一个SqlSession,多次调用同一个Mapper和同一个方法的同一个参数,只会进行一次数据库查询,然后把数据缓存到缓冲中,以后直接从缓存中取出数据,不会直接去查数据库,但是在不同的SqlSession中调用相同的方法,还是会再次发送SQL到数据库中去执行返回结果。

为了克服这个问题。需要开启二级,在SqlSessionFatory层给各个SqlSession对象共享。默认二级缓存是不开启的,需要手动进行配置。手动开启二级缓存很简单。只要开启了缓存的总开关,在Mybatis中的配置文件中settings元素设置cacheEnabled参数为True。

<settings>
   <setting name="cacheEnabled" value="true"/>
<settings/>

然后在sql映射文件中添加一行:<chche/>

这样配置的话,很多配置都会自动进行,例如:

  1. 映射文件所有的select语句会被缓存。
  2. 映射文件的所有insert、update和delete语句会刷新缓存。
  3. 缓存会使用默认的Least Recently User(LRU,最近最少使用原则)的算法来回收缓存空间。
  4. 根据时间表,比如No Flush Interval(CNFI,没有刷新间隔),缓存不会以任何时间顺序来刷新。
  5. 缓存会存储列表集合或对象的1024个引用。
  6. 缓存会被视为是read/write的缓存,意味着对象检索不是共享的,而且可以很安全地被调用者修改,不干扰其他调用者或线程所做的潜在修改。

上面的为默认属性的设置,也可以使用手动配置一些属性。

<cache eviction="LRU" flushInterval="100000" size="1024" readOnly="true"/>

  • eviction:缓存回收策略
    1. LRU:最少使用原则,移除最长时间不使用的对象。
    2. FIFO:先进先出原则,按照对象进入缓存顺序进行回收。
    3. SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象。
    4. WEAK:弱引用,更积极地移除基于垃圾回收器状态和弱引用规则的对象。
  • flushInterval:刷新时间间隔,单位为毫秒,这里配置的是100秒。如果不配置,那么只有在进行数据库修改操作时才会被动刷新缓存区。
  • size:引用额数目,代表缓存数最多可以存储的对象个数。
  • readOnly:是否只读,如果为true,则所有相同的sql语句返回的是同一个对象;如果设置为false,则相同的sql后面访问的是cache的clone副本。

当有些实时性较高的查询语句或更新语句不需要进行缓存操作的时候,我们可以在Mapper中设置。查询语句设置userCache,更新语句设置flushCache。

<select id="getUserList" resultMap="userResult" useCache="false">
    select * from t_user
</select>

<insert id="addUser" parameterType="user" flushCache="false">

二、自定义缓存

Mybatis提供了org.apache.ibatis.cache.Cache接口,用来在意缓存。新建一个CusCache类,实现Cache接口,定义一个ConcurrentHashMap<Object,Object>类型的cache来保存缓存。

public class CusCache implements Cache {
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    private ConcurrentHashMap<Object,Object> cache = new ConcurrentHashMap<>();
    private String id;
    public CusCache(){
        System.out.println("初始化1");
    }
    public CusCache(String id){
        System.out.println("初始化2");
        this.id = id;
    }
    @Override
    public String getId() {
        System.out.println("得到ID:\n" + id);
        return id;
    }
    @Override
    public void putObject(Object o, Object o1) {
        System.out.println("========put=========");
        System.out.println("KEY值:\n" + o);
        System.out.println("=====================");
        System.out.println("VALUE为:\n" + o1);
        System.out.println("=======putover=======");
        cache.put(o,o1);

    }
    @Override
    public Object getObject(Object o) {
        System.out.println("========get=========");
        System.out.println("KEY值:\n" + o);
        System.out.println("=====================");
        System.out.println("VALUE为:\n" + cache.get(o));
        System.out.println("=======getover=======");
        return cache.get(o);
    }
    @Override
    public Object removeObject(Object o) {
        System.out.println("移除缓存对象:" + o);
        return cache.remove(o);
    }
    @Override
    public void clear() {
        System.out.println("清除缓存!");
        cache.clear();
    }
    @Override
    public int getSize() {
        System.out.println("获取缓存大小!");
        return cache.size();
    }
    @Override
    public ReadWriteLock getReadWriteLock() {
        System.out.println("获取锁对象!");
        return lock;
    }
}

运行之前,需要将settings元素中的cache设置开启,设置mappers元素中cache类。

<settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
<cache type="test.mybatis.CusCache"></cache>

实现了所有的方法之后,在Test中先select两次ID为1的用户,再进行commit,commit后再进行select一次ID为1的用户,获取新对象之后再使用新对象分别select一次ID为1的用户和ID为2的用户。最后再用新对象进行commit。

@Test
public void Test() throws IOException {
    String resource = "Mybatis/mybatis-config.xml";
    Reader reader = Resources.getResourceAsReader(resource);
    SqlSessionFactory sqlSessionFactory =
		 new SqlSessionFactoryBuilder().build(reader);
    SqlSession session = sqlSessionFactory.openSession();
    String stat = "test.mybatis.DBMapping.UserMapper.getuser";
    System.out.println("第一次select id 1");
    User user = session.selectOne(stat,1);
    System.out.println("第二次selectid 1");
    user = session.selectOne(stat,1);

    System.out.println("第一次commit");
    session.commit();

    System.out.println("commit 后 select id 1");
    session.selectOne(stat,1);

    SqlSession session1 = sqlSessionFactory.openSession();
    System.out.println("新对象select id 1");
    user = session1.selectOne(stat,1);

    System.out.println("新对象select id 2");
    user = session1.selectOne(stat,2);

    System.out.println("第二次commit");
    session1.commit();
}

观察运行结果,结果有点长,读者可以不去看。。我在这里总结一下运行结果。在select id 1之前,他会先去查询这个语句所对应的key值,如果是不为空,则从这个缓存Map中取对应的value值,如果为空,则在第一次commit后再把这个key:value进行put处理。很明显,这里不管是第一次还是第二次的select id 1用key取出来的value都为空。也就是说,在commit之前,语句是不会进行任何的写缓存行为。

在第一次commit之后,再使用新对象来select id 1,这个时候再从key中取出这个语句的value时,对象不为空了,这个是因为第一次commit时将这个select id 1的语句缓存了。但在新对象中进行select id 2一样取出的value为空。这个时候如果commit就会把select id 2进行put处理。

因为我的sql语句比较长,所以运行结果很长很长,如果实在理解不了我的解释,有兴趣有耐心的朋友可以再看一下运行结果。。。。吧。。hhhhh

初始化2
得到ID:
test.mybatis.DBMapping.UserMapper
得到ID:
test.mybatis.DBMapping.UserMapper
第一次select id 1
========get=========
KEY值:
76877085:5562423982:test.mybatis.DBMapping.UserMapper.getuser:0:2147483647:select a.id as user_id,a.name as user_name,a.age as user_age,a.money as user_money
        ,b.id as card_id,b.cardNo as crad_cradNo,b.userid as card_userid,b.city as card_city,b.address as card_address
        ,c.id as course_id,c.name as course_name,c.userid as course_userid
        ,e.name as role_name,e.desp as role_desp
        from
        t_user as a
        left join card as b
        on a.id=b.userid
        left join course as c
        on a.id=c.userid
        left join user_role as d
        on a.id=d.userid
        left join role e
        on d.roleid=e.id
        where a.id=?:1:development
=====================
VALUE为:
null
=======getover=======
第二次selectid 1
========get=========
KEY值:
76877085:5562423982:test.mybatis.DBMapping.UserMapper.getuser:0:2147483647:select a.id as user_id,a.name as user_name,a.age as user_age,a.money as user_money
        ,b.id as card_id,b.cardNo as crad_cradNo,b.userid as card_userid,b.city as card_city,b.address as card_address
        ,c.id as course_id,c.name as course_name,c.userid as course_userid
        ,e.name as role_name,e.desp as role_desp
        from
        t_user as a
        left join card as b
        on a.id=b.userid
        left join course as c
        on a.id=c.userid
        left join user_role as d
        on a.id=d.userid
        left join role e
        on d.roleid=e.id
        where a.id=?:1:development
=====================
VALUE为:
null
=======getover=======
第一次commit
========put=========
KEY值:
76877085:5562423982:test.mybatis.DBMapping.UserMapper.getuser:0:2147483647:select a.id as user_id,a.name as user_name,a.age as user_age,a.money as user_money
        ,b.id as card_id,b.cardNo as crad_cradNo,b.userid as card_userid,b.city as card_city,b.address as card_address
        ,c.id as course_id,c.name as course_name,c.userid as course_userid
        ,e.name as role_name,e.desp as role_desp
        from
        t_user as a
        left join card as b
        on a.id=b.userid
        left join course as c
        on a.id=c.userid
        left join user_role as d
        on a.id=d.userid
        left join role e
        on d.roleid=e.id
        where a.id=?:1:development
=====================
VALUE为:
[Id:1 Name:张三 Age:24 Money:666.66
Card[id=1,cardNo=null,city=city,address=address,userid=1]
Course[id=1,name=name,userid=1]
Course[id=2,name=name2,userid=1]
Role[id=0,name=name,desp=desp]
Role[id=0,name=name2,desp=desp2]
]
=======putover=======
commit 后 select id 1
========get=========
KEY值:
76877085:5562423982:test.mybatis.DBMapping.UserMapper.getuser:0:2147483647:select a.id as user_id,a.name as user_name,a.age as user_age,a.money as user_money
        ,b.id as card_id,b.cardNo as crad_cradNo,b.userid as card_userid,b.city as card_city,b.address as card_address
        ,c.id as course_id,c.name as course_name,c.userid as course_userid
        ,e.name as role_name,e.desp as role_desp
        from
        t_user as a
        left join card as b
        on a.id=b.userid
        left join course as c
        on a.id=c.userid
        left join user_role as d
        on a.id=d.userid
        left join role e
        on d.roleid=e.id
        where a.id=?:1:development
=====================
VALUE为:
[Id:1 Name:张三 Age:24 Money:666.66
Card[id=1,cardNo=null,city=city,address=address,userid=1]
Course[id=1,name=name,userid=1]
Course[id=2,name=name2,userid=1]
Role[id=0,name=name,desp=desp]
Role[id=0,name=name2,desp=desp2]
]
=======getover=======
新对象select id 1
========get=========
KEY值:
76877085:5562423982:test.mybatis.DBMapping.UserMapper.getuser:0:2147483647:select a.id as user_id,a.name as user_name,a.age as user_age,a.money as user_money
        ,b.id as card_id,b.cardNo as crad_cradNo,b.userid as card_userid,b.city as card_city,b.address as card_address
        ,c.id as course_id,c.name as course_name,c.userid as course_userid
        ,e.name as role_name,e.desp as role_desp
        from
        t_user as a
        left join card as b
        on a.id=b.userid
        left join course as c
        on a.id=c.userid
        left join user_role as d
        on a.id=d.userid
        left join role e
        on d.roleid=e.id
        where a.id=?:1:development
=====================
VALUE为:
[Id:1 Name:张三 Age:24 Money:666.66
Card[id=1,cardNo=null,city=city,address=address,userid=1]
Course[id=1,name=name,userid=1]
Course[id=2,name=name2,userid=1]
Role[id=0,name=name,desp=desp]
Role[id=0,name=name2,desp=desp2]
]
=======getover=======
新对象select id 2
========get=========
KEY值:
76877270:5562423983:test.mybatis.DBMapping.UserMapper.getuser:0:2147483647:select a.id as user_id,a.name as user_name,a.age as user_age,a.money as user_money
        ,b.id as card_id,b.cardNo as crad_cradNo,b.userid as card_userid,b.city as card_city,b.address as card_address
        ,c.id as course_id,c.name as course_name,c.userid as course_userid
        ,e.name as role_name,e.desp as role_desp
        from
        t_user as a
        left join card as b
        on a.id=b.userid
        left join course as c
        on a.id=c.userid
        left join user_role as d
        on a.id=d.userid
        left join role e
        on d.roleid=e.id
        where a.id=?:2:development
=====================
VALUE为:
null
=======getover=======
第二次commit
========put=========
KEY值:
76877270:5562423983:test.mybatis.DBMapping.UserMapper.getuser:0:2147483647:select a.id as user_id,a.name as user_name,a.age as user_age,a.money as user_money
        ,b.id as card_id,b.cardNo as crad_cradNo,b.userid as card_userid,b.city as card_city,b.address as card_address
        ,c.id as course_id,c.name as course_name,c.userid as course_userid
        ,e.name as role_name,e.desp as role_desp
        from
        t_user as a
        left join card as b
        on a.id=b.userid
        left join course as c
        on a.id=c.userid
        left join user_role as d
        on a.id=d.userid
        left join role e
        on d.roleid=e.id
        where a.id=?:2:development
=====================
VALUE为:
[Id:2 Name:李四 Age:25 Money:888.88
]
=======putover=======

MyBatis

Mybatis笔记连载上篇连接Mybatis简单操作学习

Mybatis笔记连载下篇连接Mybatis动态SQL

# java  Mybatis 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×