Mybatis缓存。
注:在实际中一二级缓存的使用习惯和普遍采用的策略,这个需要慢慢积累~~~
目录
当然,第一次查询的时候,是会执行SQL语句,从数据库去提取结果的;
但是,第二次查询相同的数据的时候,第二次就会从本sqlSession的一级缓存中去提取数据了;
不同的sqlSession之间,其缓存的对象只对自己available
0.什么是缓存,为什么要引入缓存:
什么是缓存:缓存是缓冲存储的意思,是Mybatis中用于数据优化,提高程序执行效率的有效方式。
比如,第一次查询时获取到了【“婴幼儿奶粉”这条数据】,紧接着因为程序的需要,还需要重新的获取一次【“婴幼儿奶粉”这条数据】;
如果没有缓存:其需要再次从数据库中把【“婴幼儿奶粉”这条数据】提取出来;但是,要知道MySQL的数据是存储在硬盘上的,硬盘的读写速度很慢;而且,上面两次获取的都是【“婴幼儿奶粉”这条数据】;
为了优化:引入缓存,把第一次查询时获取到的【“婴幼儿奶粉”这条数据】放在某个内存的区域中,当再次需要获取【“婴幼儿奶粉”这条数据】的时候,不去读取数据库了,而是直接从内存中提取【“婴幼儿奶粉”这条数据】;内存的读取速度比硬盘快几十倍。
1.Mybatis中的缓存简介:
(1)一级缓存和二级缓存简介
(1)一级缓存:是Mybatis默认开启的,其数据对象存储的范围是SqlSession这个级别,即在同一个SqlSession处理的过程中,对同一个数据进行反复提取时,其就会利用到缓存机制,来提高程序的处理速度。
(2)二级缓存:没有默认开启,需要手动开启,其存储的范围是Mapper NameSpace。即,其范围是Mapper映射器的某个命名空间;
(注:这个范围很容易理解了,就是可访问的方位,或者数available的范围)
……………………………………………………
(2)缓存的范围
(1)存储对象:上图,比如当前程序有两个命名空间,当调用Mapper XML文件中某个命名空间(比如goods这个命名空间爱你)的SQL语句后,查询到的【“婴幼儿奶粉”这条数据】这条数据在实际存储的时候是以对象的形式存储的,而这个对象可以认为是“隶属于”该命名空间(比如goods这个命名空间)的,这个对象是被存储到了JVM内存的。。同时,Mybatis中存储对象,其本质是使用Map这种数据结构来保存的。
(2)SqlSession范围的:一级缓存:比如实际中,有3个用户,每一个用户都需要创建他自己的SqlSession会话对象;默认情况下SqlSession的一级缓存是开启的,在SqlSession中进行的数据查询工作得到的数据对象都会保存下来;;;但是在某个SqlSession中得到的任何查询结果对象,其默认的生存周期都是仅限于当前的SqlSession对象中;;;;即,每一个用户所得到的一级缓存,其只对自己有效,而且,当用户的SqlSession对象被释放的时候,存储在里面的缓存对象都会被清空。
一般,某个用户为了访问数据库,其会建立一个SqlSession对象,通常用户在进行完某一个操作后,其马上会把这个SqlSession释放掉,,,这也意味着,存储在SqlSession的一级缓存重复使用率不高,同时也可能会浪费额外的内存空间。
(3)NameSpace命名空间的:二级缓存:为了解决一级缓存的问题,引入了二级缓存。
范围隶属于goods这个命名空间的缓存对象,会被所有同命名空间中的所有的SqlSession共享。。。。(待验证问题:同一个SqlSession也可能会调用不同命名空间中的SQL哎~~~)。。。。即,他的意思是,比如SqlSession1调用了goods命名空间中的某条SQL,获取到了【“婴幼儿奶粉”这条数据】。。。。当SqlSession2还调用goods命名空间中的那条SQL,想获取【“婴幼儿奶粉”这条数据】的时候,二级缓存就起作用了。
……………………………………………………
(3)在编码中如何使用二级缓存,二级缓存的规则
(1)所有的二级缓存,默认都会为当前命名空间中的查询操作,提供缓存;而,二级缓存的开启需要在Mapper XML中进行简要配置;
(2)这么做的目的是:保证数据的一致性。设想,A用户进行写操作后(PS:由于事务的关系,写操作如果想影响到数据库需要commit啦),这个写操作已经修改了某条数据,,如果不清空缓存,当B用户来查询该条数据的时候,如果其还是从缓存中获取,(但实际上,这条数据已经被修改了),这样B用户得到的数据和数据库底层存储的就不一致了。。。。。。所以,在任何用户在commit后,都会把该NameSpace下的所有的缓存都强制清空,这样以后,后面再获取数据都需要从数据库中读取数据了,(保证数据的一致)。
说明一个问题:只有查询操作的SqlSession在commit的时候是不会清空二级缓存的,但是会清空一级缓存。● SqlSession执行更新操作(update、delete、insert)后并执行SqlSession.commit()时,不仅清空其自身的一级缓存(执行更新操作的结果),也清空二级缓存。● 但是在查询时,commit是不会清除二级缓存的,所以这里没有效果由于查询操作其实并不会改变数据,因此对数据没有影响。所以我们通常会说commit之后会将二级缓存也清空。
(3)可以设置某条SQL不使用缓存。(即,调用该SQL产生的结果对象不存储到缓存空间中吧)只需要在该SQL所在的<select>标签中,设置useCache=false;
(4)如果给某条SQL所在的<select>标签,设置flushCache=true,则表示在调用这条SQL以后,清空该NameSpace下的缓存。