Mybatis 動(dòng)態(tài)SQL

image

一、定義SQL語句

(1)select 標(biāo)簽的使用
   屬性介紹:
     id :唯一的標(biāo)識(shí)符.
     parameterType:傳給此語句的參數(shù)的全路徑名或別名 例:com.test.poso.User或user
     resultType :語句返回值類型或別名。注意,如果是集合惋鹅,那么這里填寫的
     是集合的泛型,而不是集合本身(resultType 與resultMap 不能并用)
   例子:

     sql:
      <select id="userList" parameterType="user" resultType="User">
        select * from user where name =#{name}
      </select>

(2)insert 標(biāo)簽的使用
    屬性介紹:
      id :唯一的標(biāo)識(shí)符
      parameterType:傳給此語句的參數(shù)的全路徑名或別名 例:com.test.poso.User

(3)delete 標(biāo)簽的使用
    例:

    <delete id="deleteUser" parameterType="int"> 
      delete from user 
      where id = #{id} 
    </delete>

(4)update 標(biāo)簽的使用
    類似于insert

二蜜徽、配置對(duì)象屬性與查詢結(jié)果集

(1)resultMap 標(biāo)簽的使用

基本作用:建立SQL查詢結(jié)果字段與實(shí)體屬性的映射關(guān)系信息

查詢的結(jié)果集轉(zhuǎn)換為java對(duì)象腋寨,方便進(jìn)一步操作

將結(jié)果集中的列與java對(duì)象中的屬性對(duì)應(yīng)起來并將值填充進(jìn)去

莹桅!注意:與java對(duì)象對(duì)應(yīng)的列不是數(shù)據(jù)庫中表的列名,而是查詢后結(jié)果集的列名

例:

<resultMap id="getStudentRM" type="EStudnet">
<id property="id" column="ID"/>
<result property="studentName" column="Name"/>
<result property="studentAge" column="Age"/>
</resultMap>
<select id="getStudent" resultMap="getStudentRM">
SELECT ID, Name, Age
FROM TStudent
</select>

標(biāo)簽說明:
主標(biāo)簽
id:該resultMap的標(biāo)志
type:返回值的類名尼荆,此例中返回EStudnet類
子標(biāo)簽:

id:用于設(shè)置主鍵字段與領(lǐng)域模型屬性的映射關(guān)系左腔,此處主鍵為ID,對(duì)應(yīng)id耀找。
result:用于設(shè)置普通字段與領(lǐng)域模型屬性的映射關(guān)系

三翔悠、動(dòng)態(tài)拼接SQL

(1)if 標(biāo)簽的使用

if標(biāo)簽通常用于WHERE語句中业崖,通過判斷參數(shù)值來決定是否使用某個(gè)查詢條件野芒, 他也經(jīng)常用于UPDATE語句中判斷是否更新某一個(gè)字段,還可以在INSERT語句中用來判斷是否插入某個(gè)字段的值

例:

<select id="getStudentListLikeName" parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBL ST       
WHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
</select> 

但是此時(shí)如果studentName是null或空字符串双炕,此語句很可能報(bào)錯(cuò)或查詢結(jié)果為空狞悲。此時(shí)我們使用if動(dòng)態(tài)sql語句先進(jìn)行判斷,如果值為null或等于空字符串妇斤,我們就不進(jìn)行此條件的判斷摇锋。

修改為:

<select id=" getStudentListLikeName " parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBL ST      
    <if test="studentName!=null and studentName!='' ">     
        WHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
    </if>     
</select>   

(2)foreach 標(biāo)簽的使用

foreach標(biāo)簽主要用于構(gòu)建in條件,他可以在sql中對(duì)集合進(jìn)行迭代站超。如下:

  <delete id="deleteBatch"> 

    delete from user where id in

    <foreach collection="array" item="id" index="index" open="(" close=")" separator=",">

      #{id}

    </foreach>

  </delete>

我們假如說參數(shù)為---- int[] ids = {1,2,3,4,5} ----那么打印之后的SQL如下:

  delete form user where id in (1,2,3,4,5)

釋義:

collection :collection屬性的值有三個(gè)分別是list荸恕、array、map三種死相,分別對(duì)應(yīng)的參數(shù)類型為:List融求、數(shù)組、map集合算撮,我在上面?zhèn)鞯膮?shù)為數(shù)組生宛,所以值為array

item : 表示在迭代過程中每一個(gè)元素的別名

index :表示在迭代過程中每次迭代到的位置(下標(biāo))

open :前綴

close :后綴

separator :分隔符,表示迭代時(shí)每個(gè)元素之間以什么分隔

我們通嘲构瘢可以將之用到批量刪除陷舅、添加等操作中。

(3)choose 標(biāo)簽的使用

有時(shí)候我們并不想應(yīng)用所有的條件审洞,而只是想從多個(gè)選項(xiàng)中選擇一個(gè)莱睁。MyBatis提供了choose 元素,按順序判斷when中的條件出否成立芒澜,如果有一個(gè)成立缩赛,則choose結(jié)束。當(dāng)choose中所有when的條件都不滿則時(shí)撰糠,則執(zhí)行 otherwise中的sql酥馍。類似于Java 的switch 語句,choose為switch阅酪,when為case旨袒,otherwise則為default汁针。
if是與(and)的關(guān)系,而choose是或(or)的關(guān)系砚尽。例如下面例子施无,同樣把所有可以限制的條件都寫上,方面使用必孤。選擇條件順序猾骡,when標(biāo)簽的從上到下的書寫順序:

<select id="getStudentListChooseEntity" parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBL ST      
    <where>     
        <choose>     
            <when test="studentName!=null and studentName!='' ">     
                    ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
            </when>     
            <when test="studentSex!= null and studentSex!= '' ">     
                    AND ST.STUDENT_SEX = #{studentSex}      
            </when>     
            <when test="studentBirthday!=null">     
                AND ST.STUDENT_BIRTHDAY = #{studentBirthday}      
            </when>     
            <when test="classEntity!=null and classEntity.classID !=null and classEntity.classID!='' ">     
                AND ST.CLASS_ID = #{classEntity.classID}      
            </when>     
            <otherwise>     

            </otherwise>     
        </choose>     
    </where>     
</select>     

四、格式化輸出

(1)where
當(dāng)if標(biāo)簽較多時(shí)敷搪,這樣的組合可能會(huì)導(dǎo)致錯(cuò)誤兴想。例如,like姓名赡勘,等于指定性別等:

Xml代碼

<!-- 查詢學(xué)生list嫂便,like姓名,=性別 -->     
<select id="getStudentListWhere" parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBL ST      
        WHERE      
        <if test="studentName!=null and studentName!='' ">     
            ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
        </if>     
        <if test="studentSex!= null and studentSex!= '' ">     
            AND ST.STUDENT_SEX = #{studentSex}      
        </if>     
</select>     

如果上面例子闸与,參數(shù)studentName為null或’’毙替,則或?qū)е麓藄ql組合成“WHERE AND”之類的關(guān)鍵字多余的錯(cuò)誤SQL。
這時(shí)我們可以使用where動(dòng)態(tài)語句來解決践樱。這個(gè)“where”標(biāo)簽會(huì)知道如果它包含的標(biāo)簽中有返回值的話厂画,它就插入一個(gè)‘where’。此外拷邢,如果標(biāo)簽返回的內(nèi)容是以AND 或OR 開頭的袱院,則它會(huì)剔除掉。
上面例子修改為:
Xml代碼

<!-- 查詢學(xué)生list解孙,like姓名坑填,=性別 -->     
<select id="getStudentListWhere" parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBL ST      
    <where>     
        <if test="studentName!=null and studentName!='' ">     
            ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
        </if>     
        <if test="studentSex!= null and studentSex!= '' ">     
            AND ST.STUDENT_SEX = #{studentSex}      
        </if>     
    </where>     
</select>     

(2)set
當(dāng)在update語句中使用if標(biāo)簽時(shí),如果前面的if沒有執(zhí)行弛姜,則或?qū)е露禾?hào)多余錯(cuò)誤脐瑰。使用set標(biāo)簽可以將動(dòng)態(tài)的配置SET 關(guān)鍵字,和剔除追加到條件末尾的任何不相關(guān)的逗號(hào)廷臼。
沒有使用if標(biāo)簽時(shí)苍在,如果有一個(gè)參數(shù)為null,都會(huì)導(dǎo)致錯(cuò)誤荠商,如下示例:

Xml代碼

<!-- 更新學(xué)生信息 -->     
<update id="updateStudent" parameterType="StudentEntity">     
    UPDATE STUDENT_TBL      
       SET STUDENT_TBL.STUDENT_NAME = #{studentName},      
           STUDENT_TBL.STUDENT_SEX = #{studentSex},      
           STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},      
           STUDENT_TBL.CLASS_ID = #{classEntity.classID}      
     WHERE STUDENT_TBL.STUDENT_ID = #{studentID};      
</update>     

使用set+if標(biāo)簽修改后寂恬,如果某項(xiàng)為null則不進(jìn)行更新,而是保持?jǐn)?shù)據(jù)庫原值莱没。如下示例:

Xml代碼

<!-- 更新學(xué)生信息 -->     
<update id="updateStudent" parameterType="StudentEntity">     
    UPDATE STUDENT_TBL      
    <set>     
        <if test="studentName!=null and studentName!='' ">     
            STUDENT_TBL.STUDENT_NAME = #{studentName},      
        </if>     
        <if test="studentSex!=null and studentSex!='' ">     
            STUDENT_TBL.STUDENT_SEX = #{studentSex},      
        </if>     
        <if test="studentBirthday!=null ">     
            STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},      
        </if>     
        <if test="classEntity!=null and classEntity.classID!=null and classEntity.classID!='' ">     
            STUDENT_TBL.CLASS_ID = #{classEntity.classID}      
        </if>     
    </set>     
    WHERE STUDENT_TBL.STUDENT_ID = #{studentID};      
</update>     

(3)trim
trim是更靈活的去處多余關(guān)鍵字的標(biāo)簽初肉,他可以實(shí)踐where和set的效果。
where例子的等效trim語句:

<!-- 查詢學(xué)生list饰躲,like姓名牙咏,=性別 -->     
<select id="getStudentListWhere" parameterType="StudentEntity" resultMap="studentResultMap">     
    SELECT * from STUDENT_TBL ST      
    <trim prefix="WHERE" prefixOverrides="AND|OR">     
        <if test="studentName!=null and studentName!='' ">     
            ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
        </if>     
        <if test="studentSex!= null and studentSex!= '' ">     
            AND ST.STUDENT_SEX = #{studentSex}      
        </if>     
    </trim>     
</select>     

set例子的等效trim語句:
Xml代碼

<!-- 更新學(xué)生信息 -->     
<update id="updateStudent" parameterType="StudentEntity">     
    UPDATE STUDENT_TBL      
    <trim prefix="SET" suffixOverrides=",">     
        <if test="studentName!=null and studentName!='' ">     
            STUDENT_TBL.STUDENT_NAME = #{studentName},      
        </if>     
        <if test="studentSex!=null and studentSex!='' ">     
            STUDENT_TBL.STUDENT_SEX = #{studentSex},      
        </if>     
        <if test="studentBirthday!=null ">     
            STUDENT_TBL.STUDENT_BIRTHDAY = #{studentBirthday},      
        </if>     
        <if test="classEntity!=null and classEntity.classID!=null and classEntity.classID!='' ">     
            STUDENT_TBL.CLASS_ID = #{classEntity.classID}      
        </if>     
    </trim>     
    WHERE STUDENT_TBL.STUDENT_ID = #{studentID};      
</update>     

五臼隔、配置關(guān)聯(lián)關(guān)系

(1)collection

一對(duì)一

association通常用來映射一對(duì)一的關(guān)系,例如妄壶,有個(gè)類user,對(duì)應(yīng)的實(shí)體類如下:(getter,setter方法省略)

private String id;//主鍵
private String userName;//用戶姓名

有個(gè)類Article,對(duì)應(yīng)的實(shí)體類如下:

private String id;//主鍵
private String articleTitle;//文章標(biāo)題
private String articleContent;//文章內(nèi)容

如果我想查詢一個(gè)用戶的時(shí)候摔握,也查到他寫的一篇文章,可以怎樣寫呢丁寄?在類user加入一個(gè)屬性article

private String id;//主鍵
private String userName;//用戶姓名
private Article article;//新增的文章屬性

2氨淌、mapper.xml 我在user類的mapper.xml這樣配置

<resultMap id="userResultMap" type="test.mybatis.entity.User">
<id column="id" property="id" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result column="userName" property="userName" jdbcType="VARCHAR" javaType="java.lang.String"/>
//這里把user的id傳過去
<association property="article" column="id"
select="test.mybatis.dao.articleMapper.selectArticleByUserId" />//test.mybatis.dao.articleMapper為命名空間
</resultMap>

同時(shí),我的article對(duì)應(yīng)的xml這樣寫:

<resultMap id="articleResultMap" type="test.mybatis.entity.Article">
<id column="id" property="id" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result column="articleTitle" property="articleTitle" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result column="articleContent" property="articleContent" jdbcType="VARCHAR" javaType="java.lang.String"/>
</resultMap>

(當(dāng)然伊磺,這里還有查詢user表的語句盛正,省略)

同時(shí),在article對(duì)應(yīng)的xml有這樣的select語句:

<select id="selectArticleByUserId"
parameterType="java.lang.String"
resultMap="ArticleResultMap" >
select * from
tb_article where userId=#{userId} </select>

(2)association

一對(duì)多

實(shí)體類增加對(duì)應(yīng)屬性

private String id;//主鍵
private String userName;//用戶姓名
private List<Article> articleList;
userMapper.xml這樣配置

<resultMap id="userResultMap" type="test.mybatis.entity.User">
<id column="id" property="id" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result column="userName" property="userName" jdbcType="VARCHAR" javaType="java.lang.String"/>
//這里把user的id傳過去
<collection property="articleList" column="id"
select="test.mybatis.dao.articleMapper.selectArticleListByUserId" />
</resultMap>

以下省略奢浑,類同蛮艰,Mybatis會(huì)把結(jié)果封裝成List類型腋腮。

三雀彼、如果我還想通過Article表另一張表,比如文章中有個(gè)fk_id即寡,也可以像上面這樣重復(fù)配置徊哑,把fk_id當(dāng)做與另一張表關(guān)聯(lián)的參數(shù),那時(shí)就可以通過用戶查到文章聪富,查到文章關(guān)聯(lián)的另一張表了莺丑。

六、SQL標(biāo)簽

更多用于寫sql語句的一部分墩蔓,寫在配置文件中的常量

七梢莽、include標(biāo)簽

用于引用常量

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市奸披,隨后出現(xiàn)的幾起案子昏名,更是在濱河造成了極大的恐慌,老刑警劉巖阵面,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轻局,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡样刷,警方通過查閱死者的電腦和手機(jī)仑扑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來置鼻,“玉大人镇饮,你說我怎么就攤上這事』福” “怎么了储藐?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵梅肤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我邑茄,道長(zhǎng)姨蝴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任肺缕,我火速辦了婚禮左医,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘同木。我一直安慰自己浮梢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布彤路。 她就那樣靜靜地躺著秕硝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪洲尊。 梳的紋絲不亂的頭發(fā)上远豺,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音坞嘀,去河邊找鬼躯护。 笑死,一個(gè)胖子當(dāng)著我的面吹牛丽涩,可吹牛的內(nèi)容都是我干的棺滞。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼矢渊,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼继准!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起矮男,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤移必,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后昂灵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體避凝,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年眨补,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了管削。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡撑螺,死狀恐怖含思,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤含潘,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布饲做,位于F島的核電站,受9級(jí)特大地震影響遏弱,放射性物質(zhì)發(fā)生泄漏盆均。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一漱逸、第九天 我趴在偏房一處隱蔽的房頂上張望泪姨。 院中可真熱鬧,春花似錦饰抒、人聲如沸肮砾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仗处。三九已至,卻和暖如春枣宫,著一層夾襖步出監(jiān)牢的瞬間婆誓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工镶柱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留旷档,地道東北人模叙。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓歇拆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親范咨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子故觅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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