2020-08-23

MyBatis技術(shù)總結(jié)

分類:JavaEE框架技術(shù)原創(chuàng)文章
作者:幸運(yùn)王

  • 什么是MyBatis废酷?

    MyBatis 是一款優(yōu)秀的持久層框架,它支持自定義 SQL犬第、存儲(chǔ)過程以及高級(jí)映射锦积。MyBatis 免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作。MyBatis 可以通過簡(jiǎn)單的 XML 或注解來配置和映射原始類型歉嗓、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 對(duì)象)為數(shù)據(jù)庫(kù)中的記錄背蟆。

  • MyBatis中的主要組成部分

    SqlSessionFactoryBuilder( 工廠構(gòu)造器鉴分,使用了建造者模式 ) :根據(jù)配置文件來生成SqlSessionFactory

    生命周期及其作用域:這個(gè)類可以被實(shí)例化、使用和丟棄带膀,一旦創(chuàng)建了 SqlSessionFactory志珍,就不再需要它了。 因此 SqlSessionFactoryBuilder 實(shí)例的最佳作用域是方法作用域(也就是局部方法變量)垛叨。 你可以重用 SqlSessionFactoryBuilder 來創(chuàng)建多個(gè) SqlSessionFactory 實(shí)例伦糯,但最好還是不要一直保留著它柜某,以保證所有的 XML 解析資源可以被釋放給更重要的事情。

    SqlSessionFactory(SqlSession工廠敛纲,使用到了工廠模式):創(chuàng)建SqlSession喂击。
    生命周期及其作用域:SqlSessionFactory 一旦被創(chuàng)建就應(yīng)該在應(yīng)用的運(yùn)行期間一直存在,沒有任何理由丟棄它或重新創(chuàng)建另一個(gè)實(shí)例淤翔。 使用 SqlSessionFactory 的最佳實(shí)踐是在應(yīng)用運(yùn)行期間不要重復(fù)創(chuàng)建多次翰绊,多次重建 SqlSessionFactory 被視為一種代碼“壞習(xí)慣”。因此 SqlSessionFactory 的最佳作用域是應(yīng)用作用域旁壮。 有很多方法可以做到监嗜,最簡(jiǎn)單的就是使用單例模式或者靜態(tài)單例模式。

    SqlSessionFactory創(chuàng)建代碼示例:
      private static final String CONFIG = "mybatis-config.xml"; //配置文件
      private static SqlSessionFactory sqlSessionFactory; //SqlSessionFactory對(duì)象
      private static final Class<MyBatisUtils> CLASS_LOCK = MyBatisUtils.class; //類級(jí)別鎖
    static {
          //初始化
      initSqlSessionFactory();
      }
    
      //私有的構(gòu)造方法抡谐,保證MyBatis工具類不會(huì)被實(shí)例化
      private MyBatisUtils() {
      }
    
      private static SqlSessionFactory initSqlSessionFactory() {
          if (sqlSessionFactory == null) {
              synchronized (CLASS_LOCK) {
                  try (InputStream inputStream = Resources.getResourceAsStream(CONFIG)) {
                      sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
          return sqlSessionFactory;
      }
      public static SqlSession openSqlSession() {
          if (sqlSessionFactory == null) {
              initSqlSessionFactory();
          }
          return sqlSessionFactory.openSession();
      }
    

    SqlSession(會(huì)話):用于執(zhí)行SQL并返回結(jié)果(創(chuàng)建數(shù)據(jù)庫(kù)連接+創(chuàng)建數(shù)據(jù)庫(kù)執(zhí)行操作對(duì)象+返回結(jié)果集)
    生命周期及其作用域:每個(gè)線程都應(yīng)該有它自己的 SqlSession 實(shí)例裁奇。SqlSession 的實(shí)例不是線程安全的,因此是不能被共享的麦撵,所以它的最佳的作用域是請(qǐng)求或方法作用域刽肠。 絕對(duì)不能將 SqlSession 實(shí)例的引用放在一個(gè)類的靜態(tài)域,甚至一個(gè)類的實(shí)例變量也不行厦坛。 也絕不能將 SqlSession 實(shí)例的引用放在任何類型的托管作用域中五垮,比如 Servlet 框架中的 HttpSession。 如果你現(xiàn)在正在使用一種 Web 框架杜秸,考慮將 SqlSession 放在一個(gè)和 HTTP 請(qǐng)求相似的作用域中放仗。 換句話說,每次收到 HTTP 請(qǐng)求撬碟,就可以打開一個(gè) SqlSession诞挨,返回一個(gè)響應(yīng)后,就關(guān)閉它呢蛤。 這個(gè)關(guān)閉操作很重要惶傻,為了確保每次都能執(zhí)行關(guān)閉操作,你應(yīng)該把這個(gè)關(guān)閉操作放到 try 塊中其障。 下面的示例就是一個(gè)確保 SqlSession 關(guān)閉的標(biāo)準(zhǔn)模式:

    SqlSession創(chuàng)建代碼示例:
     try (SqlSession session = sqlSessionFactory.openSession()) {
      // 應(yīng)用邏輯代碼
     }
    
  • MyBatis配置

    • 配置文件(properties)

    主要作用:加載外部的properties文件

    配置文件(properties)代碼示例:
      <properties resource="jdbc.properties"/>
    
    • 設(shè)置(settings)

    主要作用:MyBatis框架運(yùn)行規(guī)則配置

    設(shè)置(settings)代碼示例:
    <settings>
    <!-- 開啟日志 -->
    <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    
    • 類型別名(typeAliases)

    主要作用:設(shè)置別名(為實(shí)體類設(shè)置別名),可以分別為每個(gè)實(shí)體類設(shè)置別名银室,也可以統(tǒng)一為package中的每個(gè)實(shí)體類自動(dòng)設(shè)置別名

    類型別名(typeAliases)代碼示例:
    <typeAliases>
    <!-- 為每一個(gè)實(shí)體設(shè)置別名 -->
    <!-- 
    <typeAlias type="com.apesource.entity.Employee" alias="Employee"/>
    <typeAlias type="com.apesource.entity.Order" alias="Order"/>
     -->
    <!-- 設(shè)置實(shí)體類包,為該package中的每個(gè)實(shí)體類自動(dòng)設(shè)置別名 -->
    <package name="com.apesource.entity"/>
    </typeAliases>
    
    • 環(huán)境配置(environments)

    主要作用:元素體中包含了事務(wù)管理和連接池的配置

    環(huán)境配置(environments)代碼示例:
    <environments default="development">
    <!-- 環(huán)境(開發(fā)) -->
    <environment id="development">
        <!-- 事務(wù)管理器:采用JDBC事務(wù) -->
        <transactionManager type="JDBC" />
        <!-- 數(shù)據(jù)源(數(shù)據(jù)庫(kù)連接池) -->
        <!-- type設(shè)置為pooled,啟動(dòng)數(shù)據(jù)庫(kù)連接池 -->
        <dataSource type="POOLED">
            <!-- 數(shù)據(jù)庫(kù)連接參數(shù) -->
            <property name="driver" value="${driver_class}" />
            <property name="url" value="${jdbc_url}" />
            <property name="username" value="${db_username}" />
            <property name="password" value="${db_password}" />
        </dataSource>
    </environment>
    </environments>
    
    • 映射器(mappers)

    主要作用:包含了一組映射器(mapper)励翼,這些映射器的 XML 映射文件包含了 SQL 代碼和映射定義信息

    映射器(mappers)代碼示例:
    <mappers>
    <!-- SQL映射文件 -->
    <mapper resource="com/apesource/dao/mapper/AnswerRecordMapper.xml" />
    </mappers>
    
  • MyBatis XML 映射器

    1.常用節(jié)點(diǎn)作用總結(jié)

    • select:映射select查詢SQL語句
    • update:映射update修改SQL語句
    • delete:映射delete刪除SQL語句
    • insert:映射insert增加SQL語句

    2.常用屬性作用總結(jié)

    • id 屬性:為當(dāng)前映射的SQL語句進(jìn)行命名蜈敢,id應(yīng)該與xxxMapper接口下的方法名一致
    • resultType 屬性:設(shè)置查詢結(jié)果使用的類型名稱,
    • parameterType 屬性:設(shè)置執(zhí)行操作時(shí)使用的參數(shù)類型
    • useGeneratedKeys屬性:設(shè)置為true表示開啟主鍵回填(默認(rèn)為false)
    • keyProperty屬性:設(shè)置用于保存主鍵值的屬性名稱

    3.常見SQL映射示例

    示例1:普通增加

    SQL映射配置
    <insert id="insertAnswerRecord"
          parameterType="AnswerRecord"
          useGeneratedKeys="true"
          keyProperty="recordId">
    insert into answer_record(respondent,question,right_answer,submit_answer,submit_datetime)values(#{respondent},#{question},#{rightAnswer},#{submitAnswer},now())
    </insert>
    
    接口方法定義
    int insertAnswerRecord(AnswerRecord answerRecord);
    
    

    示例2:批量增加

    SQL映射配置
    <insert id="insertAnswerRecordBatch" 
        parameterType="list"
        useGeneratedKeys="true" 
        keyProperty="recordId">
    INSERT INTO
    answer_record(respondent,question,right_answer,submit_answer,submit_datetime)VALUES
    <foreach collection="list" item="record" separator=",">
        (
            #{record.respondent},
            #{record.question},
            #{record.rightAnswer},
            #{record.submitAnswer},
            now()
        )
    </foreach>
    </insert>
    
    
    接口方法定義
    int insertAnswerRecordBatch(List<AnswerRecord> answerRecordList);
    
    

    示例3:普通刪除

    SQL映射配置
    <delete id="deleteAnswerRecord">
    delete from answer_record
    where record_id = #{id}
    </delete>
    
    
    接口方法定義
    int deleteAnswerRecord(@Param("id")int recordId);
    
    

    示例4:批量刪除

    SQL映射配置
    <delete id="deleteAnswerRecordBatch"
        parameterType="list">
    DELETE FROM answer_record
    WHERE record_id IN
    <foreach collection="list" item="rid" separator="," open="(" close=")">
        #{rid}
    </foreach>
    </delete>
    
    
    接口方法定義
    int deleteAnswerRecordBatch(List<Integer> recordIdList);
    
    

    示例5:動(dòng)態(tài)修改

    SQL映射配置
    <update id="updateAnswerRecord" 
        parameterType="AnswerRecord">
    update answer_record
    <set>
        <if test="respondent!=null">respondent = #{respondent},</if>
        <if test="question!=null">question = #{question},</if>
        <if test="rightAnswer!=null">right_answer = #{rightAnswer},</if>
        <if test="submitAnswer!=null">submit_answer = #{submitAnswer},</if>
        submit_datetime = now()
    </set>
    where record_id = #{recordId}
    </update>
    
    
    接口方法定義
    int updateAnswerRecord(AnswerRecord answerRecord);
    
    

    示例6:動(dòng)態(tài)查詢

    SQL映射配置
    <select id="listAnswerRecordByCondition"
        resultType="AnswerRecord" 
        parameterType="AnswerRecord">
    SELECT record_id AS recordId,
    respondent,
    question,
    right_answer AS rightAnswer,
    submit_answer AS submitAnswer,
    submit_datetime AS submitDatetime
    FROM answer_record
    <where>
        <if test="respondent != null">AND respondent = #{respondent}</if>
        <if test="question != null">AND question LIKE concat('%',#{question},'%')</if>
        <if test="rightAnswer != null">AND right_answer = #{rightAnswer}</if>
        <if test="submitAnswer != null">AND submit_answer = #{submitAnswer}</if>
    </where>
    </select>
    
    
    接口方法定義
    List<AnswerRecord> listAnswerRecordByCondition(AnswerRecord condition);
    
    

    示例7:查詢結(jié)果封裝為Map

    SQL映射配置
    <select id="countAnswerRecordDataByRespondent"
        resultType="map">
    SELECT count(record_id) as total,
         (SELECT count(record_id) FROM answer_record WHERE respondent = #{name} AND right_answer = submit_answer ) as right_count,
         (SELECT count(record_id) FROM answer_record WHERE respondent = #{name} AND right_answer != submit_answer ) as fail_count
    FROM answer_record
    WHERE respondent = #{name}
    </select>
    
    
    接口方法定義
    Map<String,Integer> countAnswerRecordDataByRespondent(@Param("name") String respondent);
    
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末汽抚,一起剝皮案震驚了整個(gè)濱河市抓狭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌造烁,老刑警劉巖否过,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件午笛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡苗桂,警方通過查閱死者的電腦和手機(jī)药磺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來誉察,“玉大人与涡,你說我怎么就攤上這事〕制” “怎么了驼卖?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鸿秆。 經(jīng)常有香客問我酌畜,道長(zhǎng),這世上最難降的妖魔是什么卿叽? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任桥胞,我火速辦了婚禮,結(jié)果婚禮上考婴,老公的妹妹穿的比我還像新娘贩虾。我一直安慰自己,他們只是感情好沥阱,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布缎罢。 她就那樣靜靜地躺著,像睡著了一般考杉。 火紅的嫁衣襯著肌膚如雪策精。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天崇棠,我揣著相機(jī)與錄音咽袜,去河邊找鬼。 笑死枕稀,一個(gè)胖子當(dāng)著我的面吹牛询刹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播萎坷,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼范抓,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了食铐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤僧鲁,失蹤者是張志新(化名)和其女友劉穎虐呻,沒想到半個(gè)月后象泵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斟叼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年偶惠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朗涩。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡忽孽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出谢床,到底是詐尸還是另有隱情兄一,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布识腿,位于F島的核電站出革,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏渡讼。R本人自食惡果不足惜骂束,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望成箫。 院中可真熱鬧展箱,春花似錦、人聲如沸蹬昌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凳厢。三九已至账胧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間先紫,已是汗流浹背治泥。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留遮精,地道東北人居夹。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像本冲,于是被迫代替她去往敵國(guó)和親准脂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359