mybatis

參考資料

mybatis3
mybatis-spring

執(zhí)行

加載mybatis配置周叮,創(chuàng)建sqlSessionFactory

public static void setUp() throws Exception {
    Connection conn = null;

    try {
      Class.forName("org.hsqldb.jdbcDriver");
      conn = DriverManager.getConnection("jdbc:hsqldb:mem:multidb", "sa", "");

      Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/multidb/CreateDB.sql");

      ScriptRunner runner = new ScriptRunner(conn);
      runner.setLogWriter(null);
      runner.setErrorLogWriter(null);
      runner.runScript(reader);
      conn.commit();
      reader.close();

      reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/multidb/MultiDbConfig.xml");
      sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
      reader.close();
    } finally {
      if (conn != null) {
        conn.close();
      }
    }
  }
  1. 以Mapper類執(zhí)行sql
 SqlSession sqlSession = sqlSessionFactory.openSession();
MultiDbMapper mapper = sqlSession.getMapper(MultiDbMapper.class);
  1. 直接調(diào)用拨拓。
sqlSession.insert("org.apache.ibatis.submitted.selectkey.Table1.insert", parms);
sqlSession.select,update,delete

使用

基于xml和java注解的方式做映射庆尘。

這些屬性都是可外部配置且可動(dòng)態(tài)替換的,既可以在典型的 Java 屬性文件中配置,亦可通過 properties 元素的子元素來傳遞凌停。例如:

<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>

也可以把username和password 配置在config.properties文件中。
其中的屬性就可以在整個(gè)配置文件中使用來替換需要?jiǎng)討B(tài)配置的屬性值售滤。比如:

<dataSource type="POOLED">
  <property name="driver" value="${driver}"/>
  <property name="url" value="${url}"/>
  <property name="username" value="${username}"/>
  <property name="password" value="${password}"/>
</dataSource>

如果屬性在不只一個(gè)地方進(jìn)行了配置罚拟,那么 MyBatis 將按照下面的順序來加載:

  1. 在 properties 元素體內(nèi)指定的屬性首先被讀取。
  2. 然后根據(jù) properties 元素中的 resource 屬性讀取類路徑下屬性文件或根據(jù) url 屬性指定的路徑讀取屬性文件完箩,并覆蓋已讀取的同名屬性赐俗。
  3. 最后讀取作為方法參數(shù)傳遞的屬性,并覆蓋已讀取的同名屬性弊知。

因此阻逮,通過方法參數(shù)傳遞的屬性具有最高優(yōu)先級(jí),resource/url 屬性中指定的配置文件次之秩彤,最低優(yōu)先級(jí)的是 properties 屬性中指定的屬性叔扼。

sql重用(字符串替換)事哭,sql 包含(include)

<select id="select" resultType="map">
        SELECT
        ${field_name}1, ${field_name}2, ${field_name}3
        from
        <include refid="sometable">
            <property name="prefix" value="Some"/>
        </include>
    </select>

如上,字符串替換的 ${field_name} 需要配置在配置文件<configuration>的<properties>中:

  <properties>
    <property name="field_name" value="field"/>
  </properties>

如上的 <include refid="sometable"> 需要卸載<sql>中瓜富,同時(shí)通過屬性prefix傳遞了值Some:

    <sql id="sometable">
    ${prefix}Table
    </sql>

參數(shù)

#{property,javaType=int,jdbcType=NUMERIC}

參數(shù)類型由javaType確定
如果 null 被當(dāng)作值來傳遞鳍咱,對(duì)于所有可能為空的列,jdbcType 是需要的

緩存

  • 映射語(yǔ)句文件中的所有 select 語(yǔ)句將會(huì)被緩存与柑。
  • 映射語(yǔ)句文件中的所有 insert,update 和 delete 語(yǔ)句會(huì)刷新緩存谤辜。
  • 緩存會(huì)使用 Least Recently Used(LRU,最近最少使用的)算法來收回。
  • 根據(jù)時(shí)間表(比如 no Flush Interval,沒有刷新間隔), 緩存不會(huì)以任何時(shí)間順序 來刷新价捧。
  • 緩存會(huì)存儲(chǔ)列表集合或?qū)ο?無論查詢方法返回什么)的 1024 個(gè)引用丑念。
  • 緩存會(huì)被視為是 read/write(可讀/可寫)的緩存,意味著對(duì)象檢索不是共享的,而 且可以安全地被調(diào)用者修改,而不干擾其他調(diào)用者或線程所做的潛在修改。

參考文章:

  1. MyBatis的緩存
  2. 深入了解MyBatis二級(jí)緩存
    • 針對(duì)一個(gè)表的某些操作不在他獨(dú)立的namespace下進(jìn)行 ,不能用二級(jí)緩存干旧,否則會(huì)有臟數(shù)據(jù)

<cache
  eviction="FIFO"    // 緩存策略
  flushInterval="60000"   // 刷新間隔60秒
  size="512"    // 最大引用個(gè)數(shù)
  readOnly="true"/>

寫在mapper里

    <mapper namespace="org.apache.ibatis.submitted.cacheorder.Mapper">

        <!--cache-ref 引用另一個(gè)mapper文件-->
        <!--<cache-ref namespace="org.apache.ibatis.submitted.cacheorder.Mapper2"/>-->
        <cache/>

        <select id="getUser" resultType="org.apache.ibatis.submitted.cacheorder.User">
            select * from users
        </select>

    </mapper>

自定義緩存測(cè)試:


    @Test
    public void testMyCache() {
        System.out.println("---------select------------");
        SqlSession session = sqlSessionFactory.openSession(true);
        User user = session.selectOne("org.apache.ibatis.submitted.cacheorder.Mapper.getUser");
        System.out.println(user);
        session.commit();

//        System.out.println("----------update----------");
//        session = sqlSessionFactory.openSession(true);
//        session.update("org.apache.ibatis.submitted.cacheorder.Mapper.update");
//        session.commit();

        System.out.println("--------select----------");
        session = sqlSessionFactory.openSession(true);
        User user2 = session.selectOne("org.apache.ibatis.submitted.cacheorder.Mapper.getUser");
        System.out.println(user2);
        session.commit();
    }
public class MyCache implements Cache {

    private ConcurrentHashMap<Object, Object> cache = new ConcurrentHashMap<>(10);
    private ReentrantReadWriteLock            lock  = new ReentrantReadWriteLock();
    private String                            id;

    public MyCache(String id) {
        this.id = id;
    }

    @Override
    public String getId() {
        System.out.println("getId  = " + id);
        return id;
    }

    @Override
    public void putObject(Object key, Object value) {
        System.out.println("put ["+key+"] value="+value);
        cache.put(key, value);
    }

    @Override
    public Object getObject(Object key) {
        System.out.println("get objkey="+key+"  "+cache.get(key));
        return cache.get(key);
    }

    @Override
    public Object removeObject(Object key) {
        System.out.println("remove obj");
        return cache.remove(key);
    }

    @Override
    public void clear() {
        cache.clear();
    }

    @Override
    public synchronized int getSize() {
        System.out.println("getsize");
        return cache.size();
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return lock;
    }
}

配置
<cache type="org.apache.ibatis.submitted.cacheorder.MyCache"/>

我們一般會(huì)在自定義Cache里面使用Redis或者其他第三方存儲(chǔ)介質(zhì)來存數(shù)據(jù)渠欺。來提高性能,或統(tǒng)一管理椎眯。

mybatis緩存分為一級(jí)緩存和二級(jí)緩存

SqlSession commit或close之后挠将,二級(jí)緩存才會(huì)生效這個(gè)問題
二級(jí)緩存的作用域是全局的(跨session的)
一級(jí)緩存的作用域是一個(gè)session

緩存流程:

  • 查詢數(shù)據(jù)的話,先從二級(jí)緩存中拿數(shù)據(jù)编整,如果沒有的話舔稀,去一級(jí)緩存中拿,一級(jí)緩存也沒有的話再查詢數(shù)據(jù)庫(kù)掌测。
  • SqlSession commit或close之后内贮,二級(jí)緩存才會(huì)生效。
緩存執(zhí)行流程
  1. DefaultSqlSession#selectList:

  2. CachingExecutor#query: 獲取二級(jí)緩存汞斧,查二級(jí)緩存夜郁。查到直接返回
    2.1 從TransactionalCache的entriesToAddOnCommit中找

  3. 查不到則去父類BaseExecutor查:
    3.1 查一級(jí)緩存(localCache 是PerpetualCache)。
    3.2 一級(jí)緩存拿不到粘勒,數(shù)據(jù)庫(kù)拿竞端。
    3.3 TransactionalCacheManager:事務(wù)緩存管理,將需要一個(gè)事務(wù)(session)的數(shù)據(jù)緩存在TransactionalCache中的
    Map<Object, Object> entriesToAddOnCommit中庙睡。

  4. SqlSession commit或close之后 事富,調(diào)用flushPendingEntries方法將entriesToAddOnCommit中的緩存數(shù)據(jù)put到實(shí)現(xiàn)了Cache接口的緩存中(調(diào)用putObject)。所以二級(jí)緩存的作用域是全局的(跨session的)
    4.1 刪除一級(jí)緩存clearLocalCache乘陪。即把PerpetualCache的mapper數(shù)據(jù)刪除统台。所以一級(jí)緩存的作用域是一個(gè)session

Cache接口采用裝飾者設(shè)計(jì)模式

動(dòng)態(tài)sql

  <!-- 等效于 WHERE description LIKE concat('%',#{parameter},'%')   _parameter表示輸入?yún)?shù) -->
  <!-- 等效于 WHERE description LIKE '${'%' + _parameter + '%'}'-->
  <select id="selectLike" resultType="map" parameterType="string">
    <bind name="pattern" value="'%' + _parameter + '%'" />
    SELECT *
    FROM ibtest.names
    WHERE description LIKE #{pattern}
    ORDER BY id
  </select>

<bind>的value值會(huì)使用OGNL計(jì)算。

注解

  • @SelectKey 可以用來獲取自動(dòng)增長(zhǎng)的id的返回值啡邑,或者實(shí)現(xiàn)自動(dòng)增長(zhǎng)id
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贱勃,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌募寨,老刑警劉巖族展,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疫稿,死亡現(xiàn)場(chǎng)離奇詭異吓坚,居然都是意外死亡甘苍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門列肢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人宾茂,你說我怎么就攤上這事瓷马。” “怎么了跨晴?”我有些...
    開封第一講書人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵欧聘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我端盆,道長(zhǎng)怀骤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任焕妙,我火速辦了婚禮蒋伦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘焚鹊。我一直安慰自己痕届,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開白布末患。 她就那樣靜靜地躺著研叫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪璧针。 梳的紋絲不亂的頭發(fā)上嚷炉,一...
    開封第一講書人閱讀 52,158評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音陈莽,去河邊找鬼渤昌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛走搁,可吹牛的內(nèi)容都是我干的独柑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼私植,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼忌栅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤索绪,失蹤者是張志新(化名)和其女友劉穎湖员,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瑞驱,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡娘摔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了唤反。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凳寺。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖彤侍,靈堂內(nèi)的尸體忽然破棺而出肠缨,到底是詐尸還是另有隱情,我是刑警寧澤盏阶,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布晒奕,位于F島的核電站,受9級(jí)特大地震影響名斟,放射性物質(zhì)發(fā)生泄漏脑慧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一蒸眠、第九天 我趴在偏房一處隱蔽的房頂上張望漾橙。 院中可真熱鬧,春花似錦楞卡、人聲如沸霜运。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)淘捡。三九已至,卻和暖如春池摧,著一層夾襖步出監(jiān)牢的瞬間焦除,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工作彤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膘魄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓竭讳,卻偏偏與公主長(zhǎng)得像创葡,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绢慢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容