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

  • 什么是MyBatis存筏?

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

  • MyBatis中的主要組成部分

    • Resources:用于讀取配置文件讼积,并返回輸入流。
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    
    • SqlSessionFactoryBuilder(工廠構(gòu)造器):根據(jù)配置文件來生成SqlSessionFactory

    生命周期:這個類可以被實例化脚仔、使用和丟棄勤众,一旦創(chuàng)建了 SqlSessionFactory,就不再需要它了鲤脏。因此 SqlSessionFactoryBuilder實例的最佳作用域是方法作用域(也就是局部方法變量)们颜。你可以重用SqlSessionFactoryBuilder來創(chuàng)建多個SqlSessionFactory實例吕朵,但最好還是不要一直保留著它,以保證所有的 XML 解析資源可以被釋放給更重要的事情窥突。

    • SqlSessionFactory(SqlSession工廠):用于創(chuàng)建SqlSession對象努溃。

    生命周期:SqlSessionFactory 一旦被創(chuàng)建就應(yīng)該在應(yīng)用的運行期間一直存在,沒有任何理由丟棄它或重新創(chuàng)建另一個實例阻问。 使用 SqlSessionFactory 的最佳實踐是在應(yīng)用運行期間不要重復(fù)創(chuàng)建多次梧税,多次重建 SqlSessionFactory 被視為一種代碼“壞習(xí)慣”。因此 SqlSessionFactory 的最佳作用域是應(yīng)用作用域称近。 有很多方法可以做到第队,最簡單的就是使用單例模式或者靜態(tài)單例模式。

      private static SqlSessionFactory sqlSessionFactory;
      sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    
    • SqlSession(會話):用于完成對數(shù)據(jù)庫的連接煌茬、操作以及對結(jié)果集的處理等斥铺。

    生命周期:每個線程都應(yīng)該有它自己的 SqlSession 實例。SqlSession 的實例不是線程安全的坛善,因此是不能被共享的晾蜘,所以它的最佳的作用域是請求或方法作用域。 絕對不能將 SqlSession 實例的引用放在一個類的靜態(tài)域眠屎,甚至一個類的實例變量也不行剔交。 也絕不能將 SqlSession 實例的引用放在任何類型的托管作用域中,比如 Servlet 框架中的 HttpSession改衩。 如果你現(xiàn)在正在使用一種 Web 框架岖常,考慮將 SqlSession 放在一個和 HTTP 請求相似的作用域中。 換句話說葫督,每次收到 HTTP 請求竭鞍,就可以打開一個 SqlSession,返回一個響應(yīng)后橄镜,就關(guān)閉它偎快。 這個關(guān)閉操作很重要,為了確保每次都能執(zhí)行關(guān)閉操作洽胶,你應(yīng)該把這個關(guān)閉操作放到 finally 塊中晒夹。 下面的示例就是一個確保 SqlSession 關(guān)閉的標準模式:

    try (SqlSession session = sqlSessionFactory.openSession()) {
      // 你的應(yīng)用邏輯代碼
    }
    
  • MyBatis配置

    • properties

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

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

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

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

    主要作用:設(shè)置別名(為實體類設(shè)置別名)

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

    主要作用:配置事務(wù)管理和連接池

    環(huán)境配置(environments)代碼示例:
    <environments default="development">
          <!-- 環(huán)境1(開發(fā)) -->
          <environment id="development">
              <!-- 事務(wù)管理器:采用JDBC事務(wù) -->
              <transactionManager type="JDBC" />
              
              <!-- 數(shù)據(jù)源(數(shù)據(jù)庫連接池) -->
              <!-- type設(shè)置為pooled,啟動數(shù)據(jù)庫連接池 -->
              <dataSource type="POOLED">
                  <!-- 數(shù)據(jù)庫連接參數(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)

    主要作用:配置映射器姊氓,這些映射器的 XML 映射文件包含了SQL代碼和映射定義信息

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

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

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

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

    • id 屬性:為當前映射的SQL語句進行命名
    • resultType 屬性:設(shè)置查詢結(jié)果使用的類型名稱
    • parameterType 屬性:設(shè)置參數(shù)使用的類型名稱
    • useGeneratedKeys屬性:開啟主鍵回填
    • keyProperty屬性:設(shè)置用于保存主鍵值的屬性名稱

    3.常見SQL映射示例

    示例1:普通增加

    <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:批量增加

    <!-- 批量添加新答題記錄 -->
    <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:普通刪除

    <delete id="deleteAnswerRecord" >
              delete from answer_record
              where record_id = #{id}
    </delete>
    
    // 接口方法定義
    int deleteAnswerRecord(int recordId);
    

    示例4:批量刪除

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

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

      <!-- set節(jié)點用于動態(tài)處理update語句中的set -->
      <!-- if節(jié)點用于條件判斷 -->
      <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:動態(tài)查詢

    <!-- where節(jié)點:處理where子句和條件之間的關(guān)系 -->
    <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 ar);
    

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

    <select id="countAnswerRecordDataByRespondent" resultType="Map">
          select count(record_id) as '總答題數(shù)目',
                    (select count(record_id) from answer_record where respondent = #{name} and right_answer = submit_answer) as '正確題目數(shù)目',
                    (select count(record_id) from answer_record where respondent = #{name} and right_answer != submit_answer) as '錯誤題目數(shù)目'
          from answer_record
          where respondent = #{name}
    </select>
    
    // 接口方法定義
    Map<String,Integer> countAnswerRecordDataByRespondent(String respondent);
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丐怯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子翔横,更是在濱河造成了極大的恐慌读跷,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件禾唁,死亡現(xiàn)場離奇詭異舔亭,居然都是意外死亡些膨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門钦铺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肢预,你說我怎么就攤上這事矛洞。” “怎么了烫映?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵沼本,是天一觀的道長。 經(jīng)常有香客問我锭沟,道長抽兆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任族淮,我火速辦了婚禮辫红,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘祝辣。我一直安慰自己贴妻,他們只是感情好,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布蝙斜。 她就那樣靜靜地躺著名惩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪孕荠。 梳的紋絲不亂的頭發(fā)上娩鹉,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音稚伍,去河邊找鬼弯予。 笑死,一個胖子當著我的面吹牛槐瑞,可吹牛的內(nèi)容都是我干的熙涤。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼困檩,長吁一口氣:“原來是場噩夢啊……” “哼祠挫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悼沿,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤等舔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后糟趾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體慌植,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡甚牲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蝶柿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丈钙。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖交汤,靈堂內(nèi)的尸體忽然破棺而出雏赦,到底是詐尸還是另有隱情,我是刑警寧澤芙扎,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布星岗,位于F島的核電站,受9級特大地震影響戒洼,放射性物質(zhì)發(fā)生泄漏俏橘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一圈浇、第九天 我趴在偏房一處隱蔽的房頂上張望寥掐。 院中可真熱鬧,春花似錦汉额、人聲如沸曹仗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽怎茫。三九已至,卻和暖如春妓灌,著一層夾襖步出監(jiān)牢的瞬間轨蛤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工虫埂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留祥山,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓掉伏,卻偏偏與公主長得像缝呕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子斧散,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345