久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Mybatis一級(jí),、二級(jí)緩存

 觀(guān)審美2 2016-11-30

一級(jí)緩存

首先做一個(gè)測(cè)試,,創(chuàng)建一個(gè)mapper配置文件和mapper接口,我這里用了最簡(jiǎn)單的查詢(xún)來(lái)演示,。

<mapper namespace="cn.elinzhou.mybatisTest.mapper.UserMapper">

    <select id="findUsers" resultType="cn.elinzhou.mybatisTest.pojo.User">
        SELECT * FROM user
    </select>
</mapper>
public interface UserMapper {
    List<User> findUsers()throws Exception;
}

然后編寫(xiě)一個(gè)單元測(cè)試

public class UserMapperTest {


    SqlSession sqlSession = null;
    @Before
    public void setUp() throws Exception {
        // 通過(guò)配置文件獲取數(shù)據(jù)庫(kù)連接信息
        Reader reader = Resources.getResourceAsReader("cn/elinzhou/mybatisTest/config/mybatis.xml");
        // 通過(guò)配置信息構(gòu)建一個(gè)SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        // 通過(guò)sqlSessionFactory打開(kāi)一個(gè)數(shù)據(jù)庫(kù)會(huì)話(huà)
        sqlSession = sqlSessionFactory.openSession();
    }

    @Test
    public void testFindUsers() throws Exception {
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.findUsers();
        System.out.println(users);
    }
}

運(yùn)行,,可以看到控制臺(tái)輸出(先配好log4j)為類(lèi)似如下圖日志
技術(shù)分享

日志說(shuō)明了該操作執(zhí)行的sql語(yǔ)句已經(jīng)查詢(xún)的內(nèi)容,最后一行是我手動(dòng)通過(guò)System.out.printf輸出的結(jié)果,。

然后再加一條語(yǔ)句

users = userMapper.findUsers();

之前的單元測(cè)試就變成了這個(gè)樣子

技術(shù)分享

也就是在執(zhí)行完userMapper.findUsers();后立刻再執(zhí)行一遍userMapper.findUsers(); 可以想象,,其實(shí)這兩個(gè)操作執(zhí)行的sql是完全相同的,而且在這期間沒(méi)有對(duì)數(shù)據(jù)庫(kù)進(jìn)行過(guò)其他操作,。然后執(zhí)行該單元測(cè)試,,發(fā)現(xiàn)效果跟上面執(zhí)行一條的時(shí)候完全相同,也就是執(zhí)行第二次userMapper.findUsers();操作的時(shí)候沒(méi)有對(duì)數(shù)據(jù)庫(kù)進(jìn)行查詢(xún),,那么得到的數(shù)據(jù)是從哪里來(lái)的,?答案是一級(jí)緩存。

mybatis一級(jí)緩存是指在內(nèi)存中開(kāi)辟一塊區(qū)域,,用來(lái)保存用戶(hù)對(duì)數(shù)據(jù)庫(kù)的操作信息(sql)和數(shù)據(jù)庫(kù)返回的數(shù)據(jù),,如果下一次用戶(hù)再執(zhí)行相同的請(qǐng)求,那么直接從內(nèi)存中讀數(shù)數(shù)據(jù)而不是從數(shù)據(jù)庫(kù)讀取。
其中數(shù)據(jù)的生命周期有兩個(gè)影響因素,。

  1. 對(duì)sqlsession執(zhí)行commit操作時(shí)

對(duì)sqlsession執(zhí)行commit操作,,也就意味著用戶(hù)執(zhí)行了update、delete等操作,,那么數(shù)據(jù)庫(kù)中的數(shù)據(jù)勢(shì)必會(huì)發(fā)生變化,,如果用戶(hù)請(qǐng)求數(shù)據(jù)仍然使用之前內(nèi)存中的數(shù)據(jù),那么將讀到臟數(shù)據(jù),。所以在執(zhí)行sqlsession操作后,,會(huì)清除保存數(shù)據(jù)的HashMap,用戶(hù)在發(fā)起查詢(xún)請(qǐng)求時(shí)就會(huì)重新讀取數(shù)據(jù)并放入一級(jí)緩存中了,。

技術(shù)分享

技術(shù)分享

上述測(cè)試就是在第一查詢(xún)完后執(zhí)行了commit操作,,再進(jìn)行查詢(xún)。與之前的測(cè)試不同的是,,這次測(cè)試控制臺(tái)打印了兩組查詢(xún)結(jié)果,,說(shuō)明在commit之后mybatis對(duì)數(shù)據(jù)重新進(jìn)行了查詢(xún)。

  1. 關(guān)閉sqlsession

一般在mybatis集成spring時(shí),,會(huì)把SqlSessionFactory設(shè)置為單例注入到IOC容器中,,不把sqlsession也設(shè)置為單例的原因是sqlsession是線(xiàn)程不安全的,所以不能為單例,。那也就意味著其實(shí)是有關(guān)閉sqlsession的過(guò)程的,。其實(shí),對(duì)于每一個(gè)service中的sqlsession是不同的,,這是通過(guò)mybatis-spring中的org.mybatis.spring.mapper.MapperScannerConfigurer創(chuàng)建sqlsession自動(dòng)注入到service中的,。
而一級(jí)緩存的設(shè)計(jì)是每個(gè)sqlsession單獨(dú)使用一個(gè)緩存空間,,不同的sqlsession是不能互相訪(fǎng)問(wèn)數(shù)據(jù)的,。當(dāng)然,在sqlsession關(guān)閉后,,其中數(shù)據(jù)自然被清空,。

二級(jí)緩存

在使用二級(jí)緩存之前,先測(cè)試之前提到過(guò)的關(guān)閉sqlsession后會(huì)清空緩存的問(wèn)題,,把junit代碼修改一下

@Test
    public void testFindUsers() throws Exception {
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.findUsers();
        //關(guān)閉sqlsession
        sqlSession.close();

        //通過(guò)sqlsessionFactroy創(chuàng)建一個(gè)新的sqlsession
        sqlSession = sqlSessionFactory.openSession();
        //獲取mapper對(duì)象
        userMapper = sqlSession.getMapper(UserMapper.class);
        users = userMapper.findUsers();
        System.out.println(users);
    }

這段代碼在第一次查詢(xún)完后關(guān)閉sqlsession,,然后創(chuàng)建新的sqlsession和mapper來(lái)重新執(zhí)行一次查詢(xún)操作,可以預(yù)見(jiàn),,執(zhí)行結(jié)果如圖

技術(shù)分享

說(shuō)明關(guān)閉了sqlsession后的確把之前的緩存數(shù)據(jù)清空了,,之后再執(zhí)行同樣的查詢(xún)操作也會(huì)再訪(fǎng)問(wèn)一遍數(shù)據(jù)庫(kù)。為了解決這個(gè)問(wèn)題,,需要使用二級(jí)緩存

一級(jí)緩存的作用域僅限于一個(gè)sqlsession,,但是二級(jí)緩存的作用域是一個(gè)namespace。但并不是意味著同一個(gè)namespace創(chuàng)建的mapper可以互相讀取緩存內(nèi)容,這里的原則是,,如果開(kāi)啟了二級(jí)緩存,,那么在關(guān)閉sqlsession后,會(huì)把該sqlsession一級(jí)緩存中的數(shù)據(jù)添加到namespace的二級(jí)緩存中,。

接下測(cè)試,,先需要開(kāi)啟二級(jí)緩存。

1.打開(kāi)二級(jí)緩存總開(kāi)關(guān)
打開(kāi)總開(kāi)關(guān),,只需要在mybatis總配置文件中加入一行設(shè)置

<settings>
   <!--開(kāi)啟二級(jí)緩存-->
    <setting name="cacheEnabled" value="true"/>
</settings>

2.打開(kāi)需要使用二級(jí)緩存的mapper的開(kāi)關(guān)

在需要開(kāi)啟二級(jí)緩存的mapper.xml中加入caceh標(biāo)簽

<cache/>

3.POJO序列化

讓需要使用二級(jí)緩存的POJO類(lèi)實(shí)現(xiàn)Serializable接口,,如

public class User implements Serializable {

通過(guò)之前三步操作就可以使用二級(jí)緩存了,接下來(lái)測(cè)試,。添加一個(gè)Junit方法

@Test
    public void testFindUsersCache() throws Exception {
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.findUsers();
        //關(guān)閉sqlsession
        sqlSession.close();

        //通過(guò)sqlsessionFactroy創(chuàng)建一個(gè)新的sqlsession
        sqlSession = sqlSessionFactory.openSession();
        //獲取mapper對(duì)象
        userMapper = sqlSession.getMapper(UserMapper.class);
        users = userMapper.findUsers();
        System.out.println(users);
    }

執(zhí)行后可以發(fā)現(xiàn),,控制臺(tái)值輸出了一次查詢(xún)過(guò)程,也可以證明二級(jí)緩存開(kāi)啟成功,。

還有一個(gè)問(wèn)題,,之前說(shuō)了,即使開(kāi)啟了二級(jí)緩存,,不同的sqlsession之間的緩存數(shù)據(jù)也不是想互訪(fǎng)就能互訪(fǎng)的,,必須等到sqlsession關(guān)閉了以后,才會(huì)把其一級(jí)緩存中的數(shù)據(jù)寫(xiě)入二級(jí)緩存,。為了測(cè)試這個(gè),,把上述代碼中的

sqlSession.close();

注釋?zhuān)敲粗暗拇a就變成了
技術(shù)分享

再執(zhí)行,發(fā)現(xiàn)控制太又輸出了兩次的查詢(xún)過(guò)程,,所以可以印證,,只有關(guān)閉了sqlsession之后,才會(huì)把其中一級(jí)緩存數(shù)據(jù)寫(xiě)入二級(jí)緩存,。

緩存配置

  • 關(guān)閉刷新

在默認(rèn)情況下,,當(dāng)sqlsession執(zhí)行commit后會(huì)刷新緩存,但是也可以強(qiáng)制設(shè)置為不刷新,,在不需要刷新的標(biāo)簽中加入

flushCache="false" 

<select id="findUsers" resultType="cn.elinzhou.mybatisTest.pojo.User" flushCache="false">

那么,,無(wú)論是否執(zhí)行commit,緩存都不會(huì)刷新了,。但是這樣會(huì)造成臟讀,,只有在特殊情況下才使用

  • 自動(dòng)刷新

有些情況下,需要設(shè)置自動(dòng)刷新緩存,,那么需要配置對(duì)應(yīng)mapper中的cache標(biāo)簽,。

flushInterval="10000"

該屬性表示每隔10秒鐘自動(dòng)刷新一遍緩存

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,,不代表本站觀(guān)點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多