mybatis基礎(chǔ)

使用原生jdbc的問(wèn)題
  1. 數(shù)據(jù)庫(kù)連接摧玫, 使用時(shí)就創(chuàng)建拌夏,不使用就立即釋放赵辕,對(duì)數(shù)據(jù)庫(kù)進(jìn)行頻繁地鏈接開(kāi)啟和關(guān)閉,造成數(shù)據(jù)庫(kù)資源浪費(fèi)身辨,影響數(shù)據(jù)庫(kù)性能丐谋。
    解決方案: 使用數(shù)據(jù)庫(kù)連接池管理數(shù)據(jù)庫(kù)連接。
    2.將sql語(yǔ)句硬編碼到j(luò)ava代碼中栅表,如果sql語(yǔ)句修改笋鄙,需要重新編譯java代碼,不利于系統(tǒng)維護(hù)怪瓶。
    設(shè)想:將sql 語(yǔ)句配置到xml文件中萧落。
    3.向preparedStatement中設(shè)置參數(shù),設(shè)置占位符號(hào)位置洗贰,以及對(duì)應(yīng)的參數(shù)值屬于硬編碼找岖,不利于系統(tǒng)維護(hù)。
    設(shè)想 將sql語(yǔ)句及占位符號(hào)和全部參數(shù)配置在xml中敛滋。
    4.從resultset中遍歷結(jié)果集數(shù)據(jù)時(shí)存在硬編碼许布,將獲取表的字段進(jìn)行成硬編碼,不利于系統(tǒng)維護(hù)绎晃。
    設(shè)想:將查詢(xún)結(jié)果集蜜唾,自動(dòng)映射成java對(duì)象杂曲。

mybatis和hibernate的區(qū)別和應(yīng)用場(chǎng)景

hibernate:是一個(gè)ORM框架(對(duì)象關(guān)系映射),不需要程序?qū)憇ql, sql語(yǔ)句自動(dòng)生成了袁余。
對(duì)sql語(yǔ)句進(jìn)行優(yōu)化擎勘、修改比較困難。
mybatis:專(zhuān)注sql本身颖榜,需要程序員自己編寫(xiě)sql語(yǔ)句棚饵,sql修改、優(yōu)化比較方便掩完。mybatis是一個(gè)不完全的ORM框架噪漾,雖然程序員自己寫(xiě)sql,mybatis也可以實(shí)現(xiàn)映射(輸入映射、輸出映射)且蓬。
應(yīng)用場(chǎng)景:
適用于需求變化比較多的項(xiàng)目欣硼,比如:互聯(lián)網(wǎng)項(xiàng)目。

mybatis 開(kāi)發(fā)dao的方法

SqlSessionBuilder作為工具類(lèi)創(chuàng)建SqlSessionFactory
SqlSessionFactory使用單例模式
SqlSession是線程不安全的缅疟,在SqlSession實(shí)現(xiàn)類(lèi)中除了有接口中方法還有數(shù)據(jù)域?qū)傩浴?/p>

總結(jié)原始dao開(kāi)發(fā)問(wèn)題
  1. statement 的id需要在代碼中調(diào)用分别,屬于硬編碼
  2. 調(diào)用sqlsession方法時(shí)傳入的變量,由于sqlsession方法使用泛型存淫,即使變量類(lèi)型傳入錯(cuò)誤,在編譯階段也不報(bào)錯(cuò)
  3. dao接口實(shí)現(xiàn)類(lèi)方法中存在大量模板方法沼填,設(shè)想能否將這些代碼提取出來(lái)桅咆。

mapper 代理方法

程序員只需要實(shí)現(xiàn)mapper接口(相當(dāng)于dao接口)
程序員還需要編寫(xiě)mapper.xml映射文件
需要遵循一個(gè)規(guī)范

  1. mapper.xml 中namespace 就是mapper.java 的全限定名
  2. mapper.xml 中statement 的id 就是 mapper.java 的方法名一致
  3. mapper.xml 中statement 的parameterType 指定輸入?yún)?shù)類(lèi)型和mapper.java的方法輸入,參數(shù)類(lèi)型一致坞笙。
  4. mapper.xml 中statement 的resultType 指定輸出結(jié)果的類(lèi)型和mapper.java的返回方法值類(lèi)型一致岩饼。
mapper 接口方法參數(shù)只能有一個(gè)是否影響系統(tǒng)開(kāi)發(fā)

mapper接口方法參數(shù)只能有一個(gè),系統(tǒng)是否不利于擴(kuò)展維護(hù)薛夜?
解決
系統(tǒng)框架中籍茧,dao層的代碼是被業(yè)務(wù)層公用的。
即使mapper接口只有一個(gè)參數(shù)梯澜,可以使用包裝類(lèi)型的pojo滿(mǎn)足不同的業(yè)務(wù)方法的需求寞冯。
注意
持久層方法參數(shù)可以包裝類(lèi)型,但是service 方法中建議不要使用包裝類(lèi)型(不利于業(yè)務(wù)層可擴(kuò)展性)晚伙。

將sql連接信息寫(xiě)入db.properties文件中
mybatis 配置

settings

typeAliases

用于配置單個(gè)類(lèi)的別名或者整個(gè)包的別名

typeHandlers

實(shí)現(xiàn)java類(lèi)和jdbc類(lèi)型的相互轉(zhuǎn)化吮龄,由mybatis的一系列類(lèi)型handler實(shí)現(xiàn)。

mapper 配置

單個(gè)映射文件加載使用
<mapper class="com.vee.mybatis.mapper.UserMapper"></mapper>
批量加載
<package name="com.vee.mybatis.mapper"></package>
使用條件
使用package進(jìn)行批量加載,要求與使用class一樣需要將mapper接口和xml映射文件名稱(chēng)保持一致咆疗,且在一個(gè)目錄中漓帚。

Vo包裝pojo類(lèi)
  • 通過(guò)創(chuàng)建子類(lèi)對(duì)pojo 類(lèi)進(jìn)行擴(kuò)展
  • 創(chuàng)建vo類(lèi)包裝pojo類(lèi)可以實(shí)現(xiàn)多表聯(lián)合查詢(xún)
  • 使用Vo 類(lèi)可以利用成員中的pojo類(lèi)或者pojo擴(kuò)展類(lèi),實(shí)現(xiàn)多參數(shù)查詢(xún)午磁。
resultType

使用resultType 進(jìn)行輸出映射尝抖,只要查詢(xún)出來(lái)的列名和Pojo中的屬性名一致毡们,該列才可以映射成功。
如果查詢(xún)出來(lái)的列名和pojo中的屬性名全部不一致昧辽,沒(méi)有創(chuàng)建pojo對(duì)象漏隐。
只要查詢(xún)出來(lái)的列名和pojo中的屬性有一個(gè)一致,就會(huì)創(chuàng)建pojo對(duì)象奴迅。

resultMap

如果查詢(xún)出來(lái)的列名和pojo的屬性名不一致青责,通過(guò)定義一個(gè)resultMap對(duì)列名和pojo屬性名之間作一個(gè)映射關(guān)系。

  • 定義resultMap
  • 使用resultMap作為statement的輸出映射類(lèi)型

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

mysql核心 對(duì)sql語(yǔ)句進(jìn)行靈活操作取具,對(duì)sql進(jìn)行靈活拼接組裝

例如:
對(duì)查詢(xún)條件進(jìn)行判斷脖隶, 如果輸入?yún)?shù)不為空才進(jìn)行查詢(xún)條件拼接。
使用它可以防止空指針異常

    <select id="findUserList4" parameterType="UserQueryVo" resultType="UserCustom">
        SELECT * FROM USER
        <where>
          <if test="userCustom.uid!=0">
              AND uid = #{userCustom.uid}
          </if>
          <if test="userCustom.uname!=null">
              AND uname LIKE '%${userCustom.uname}%'
          </if>
        </where>
  </select>
sql 片段

將上邊實(shí)現(xiàn)的動(dòng)態(tài)sql 判斷代碼塊抽取出來(lái)暇检,組成一個(gè)sql 片段产阱。其他的statement中就可以引用sql片段。

  • sql 片段可以提高sql代碼的可重用性
  • sql 片段建議基于單表
  • sql 片段不用包含where防止使用多個(gè)sql片段時(shí)where 重復(fù)
foreach

向sql傳遞數(shù)組或List块仆,mybatis 使用foreach解析
例如如下的sql語(yǔ)句
select * from user where id=1 or id=2 or id=10
或者
select * from user where id IN(1,2,10)
這就需要在輸入?yún)?shù)類(lèi)型中添加List<Integer> ids

<select id="findUserList6" parameterType="UserQueryVo2" resultType="UserCustom">
        SELECT * FROM USER
        <where>
            <if test="userCustom!=null">
                AND uname LIKE '%${userCustom.uname}%'
            </if>
            <if test="ids!=null">
                <foreach collection="ids" item="id" open="and (" close=")" separator="or">
                    uid=#{id}
                </foreach>
            </if>
        </where>
    </select>
一對(duì)一查詢(xún)

做法:
對(duì)需要用到的屬性較多的類(lèi)進(jìn)行擴(kuò)展构蹬,并將另一個(gè)類(lèi)的屬性作為字段傳入。
使用resultMap
在<resultMap>標(biāo)簽中使用<association>標(biāo)簽映射關(guān)聯(lián)查詢(xún)單個(gè)對(duì)象的信息,property:將要關(guān)聯(lián)查詢(xún)的用戶(hù)信息映射到Orders中哪個(gè)屬性悔据。

總結(jié):
resultType:如果沒(méi)有查詢(xún)結(jié)果的特殊要求建議使用resultType庄敛,如果pojo中沒(méi)有包括查詢(xún)出來(lái)的列名,需要在擴(kuò)展類(lèi)中增加列名對(duì)應(yīng)的屬性科汗。
resultMap:需要單獨(dú)定義resultMap,如果對(duì)查詢(xún)結(jié)果有特殊要求(列名和pojo中的屬性名稱(chēng)不匹配)可以使用resulMap對(duì)屬性名和列名進(jìn)行映射藻烤。

一對(duì)多查詢(xún)

做法:

  • 使用resultType,創(chuàng)建新pojo包含必要屬性,然后返回pojo列表
  • 使用resultMap头滔,擴(kuò)展類(lèi)添加List<>屬性,需要使用<resultMap>內(nèi)部標(biāo)簽中的<collection>標(biāo)簽怖亭。
多對(duì)多查詢(xún)

resultMap的可以在pojo中有List的時(shí)候在<resultMap>標(biāo)簽中定義collection,并且collection中可以遞歸定義collection坤检,但是這種場(chǎng)景往往使用resultType 兴猩,利用擴(kuò)展的pojo類(lèi)也可以很輕松地完成功能。
但是有的需求確實(shí)需要一個(gè)類(lèi)有一個(gè)list成員早歇,這個(gè)時(shí)候還是resultMap適合倾芝。

resultMap和resultType小結(jié)

resultType和resultMap都可以完成高級(jí)結(jié)果映射,如果沒(méi)有特殊要求缺前,使用resultType方便蛀醉,resultType和resultMap 的一個(gè)主要區(qū)別就是要應(yīng)用場(chǎng)景不同resultType主要是查詢(xún)明細(xì)使用,resultMap主要是層級(jí)查詢(xún)使用衅码,比如查詢(xún)用戶(hù)信息拯刁,如何點(diǎn)擊查詢(xún)訂單,再去查詢(xún)訂單信息逝段,resultMap可以實(shí)現(xiàn)延遲加載垛玻,而resultType沒(méi)有該功能割捅。

延遲加載

resultMap 可以實(shí)現(xiàn)高級(jí)映射(使用association、實(shí)現(xiàn)一對(duì)一和一對(duì)多映射)帚桩,association亿驾、collection具備延遲加載功能。
延遲加載:先從單表查詢(xún)账嚎、需要時(shí)再?gòu)年P(guān)聯(lián)表去關(guān)聯(lián)查詢(xún)莫瞬,大大提高數(shù)據(jù)庫(kù)性能。
使用resultMap 中的association 去實(shí)現(xiàn)延遲加載郭蕉。
select 屬性可以執(zhí)行statement的id

  • mybatis默認(rèn)沒(méi)有開(kāi)啟延遲加載疼邀,需要在sqlMapConfig.xml中setting 配置。
設(shè)置項(xiàng) 描述 允許值 默認(rèn)值
lazyLoadingEnable Globally enables or disables lazy loading. When enabled, all relations will be lazily loaded. true/false false
aggressiveLazyLoading(不常用) When enabled, any method call will load all the lazy properties of the object. Otherwise, each property is loaded on demand true/false false (true in ≤3.4.1)
  • 不使用延遲加載也是可以完成功能的召锈,延遲加載的本質(zhì)是延遲sql查詢(xún)的時(shí)間旁振,那么使用不同的mapper也可以完成先單表查詢(xún),然后一些屬性按需查詢(xún)的功能

resultType涨岁、resultMap拐袜、延遲加載使用場(chǎng)景總結(jié)

  • 延遲加載:
    mybatis 提供 的延遲加載功能用于service 層,要在對(duì)象消亡之前進(jìn)行
  • resultType
    將明細(xì)記錄映射到對(duì)應(yīng)的pojo中
  • resultMap
    使用association 和collection 完成一對(duì)一和一對(duì)多的高級(jí)映射
  • association
    將關(guān)聯(lián)查詢(xún)信息映射到一個(gè)pojo類(lèi)中梢薪。
  • collection
    將關(guān)聯(lián)查詢(xún)信息映射到到一個(gè)list集合中蹬铺。

查詢(xún)緩存

使用緩存可以將熱數(shù)據(jù)放在內(nèi)存中,用戶(hù)查詢(xún)數(shù)據(jù)就不用從磁盤(pán)上查詢(xún)沮尿,這樣可以提高查詢(xún)效率丛塌,解決了高并發(fā)系統(tǒng)的性能問(wèn)題。
mybatis中二級(jí)緩存生存與sqlSession中畜疾,二級(jí)緩存是mapper級(jí)別的緩存,二級(jí)緩存是可以被不同的sqlSession共享的印衔。

一級(jí)緩存

第一次查詢(xún)一個(gè)sql啡捶,sql 查詢(xún)結(jié)果寫(xiě)入sqlsession 緩存中,同一個(gè)sqlsession 再次發(fā)出相同的sql 奸焙,就從緩存中取瞎暑。如果兩次中間出現(xiàn)了commit曹組,本sqlsession 中的一級(jí)緩存區(qū)域就全部清空与帆。
mybatis默認(rèn)支持一級(jí)緩存了赌,但是mybatis 和spring整合后進(jìn)行mapper代理開(kāi)發(fā),不支持一級(jí)緩存玄糟。mybatis 和spring整合勿她,spring按照mapper模板去生成mapper代理對(duì)象,模板中在最后統(tǒng)一關(guān)閉了sqlsession阵翎。

二級(jí)緩存

二級(jí)緩存的范圍是mapper級(jí)別(mapper同一個(gè)命名空間)逢并,mapper以命名空間為單位創(chuàng)建緩存數(shù)據(jù)結(jié)構(gòu)之剧。

  • mybatis開(kāi)啟二級(jí)緩存
    <setting name="cacheEnabled" value="true">
    還需要在mapper.xml中添加<cache />標(biāo)簽。
  • 查詢(xún)結(jié)果映射的pojo需要序列化砍聊,實(shí)現(xiàn)java.io.serializable接口背稼。
    二級(jí)緩存可以將內(nèi)存的數(shù)據(jù)寫(xiě)到磁盤(pán),存在對(duì)象的序列化和反序列化玻蝌,所以要實(shí)現(xiàn)java.io.serializable 接口蟹肘。
  • 一個(gè)sqlSession 在close的時(shí)候會(huì)將緩存寫(xiě)入到公有緩存(磁盤(pán)上)。
  • 單個(gè)statement 禁止使用二級(jí)緩存俯树。
    <select id="findUserList6" parameterType="UserQueryVo" resultType="UserCustom" useCache="false">
    對(duì)于變化頻率較高的select帘腹,需要禁用二級(jí)緩存,即該sql使用二級(jí)緩存聘萨。
  • 如果sqlSession進(jìn)行commit操作竹椒,刷新緩存(全局清空)。
    設(shè)置statement 的flushCache 是否刷新緩存米辐,默認(rèn)值是true胸完,設(shè)置為false可能導(dǎo)致臟讀。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翘贮,一起剝皮案震驚了整個(gè)濱河市赊窥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌狸页,老刑警劉巖锨能,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異芍耘,居然都是意外死亡址遇,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)斋竞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)倔约,“玉大人,你說(shuō)我怎么就攤上這事坝初〗#” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵鳄袍,是天一觀的道長(zhǎng)绢要。 經(jīng)常有香客問(wèn)我,道長(zhǎng)拗小,這世上最難降的妖魔是什么重罪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上蛆封,老公的妹妹穿的比我還像新娘唇礁。我一直安慰自己,他們只是感情好惨篱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布盏筐。 她就那樣靜靜地躺著,像睡著了一般砸讳。 火紅的嫁衣襯著肌膚如雪琢融。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天簿寂,我揣著相機(jī)與錄音漾抬,去河邊找鬼。 笑死常遂,一個(gè)胖子當(dāng)著我的面吹牛纳令,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播克胳,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼平绩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了漠另?” 一聲冷哼從身側(cè)響起捏雌,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎笆搓,沒(méi)想到半個(gè)月后性湿,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡满败,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年肤频,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片算墨。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡着裹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出米同,到底是詐尸還是另有隱情,我是刑警寧澤摔竿,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布面粮,位于F島的核電站,受9級(jí)特大地震影響继低,放射性物質(zhì)發(fā)生泄漏熬苍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望柴底。 院中可真熱鬧婿脸,春花似錦、人聲如沸柄驻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鸿脓。三九已至抑钟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間野哭,已是汗流浹背在塔。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拨黔,地道東北人蛔溃。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像篱蝇,于是被迫代替她去往敵國(guó)和親贺待。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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