MyBatis動態(tài)SQL

? ? ? ?在講MyBatis動態(tài)SQL之前,先教大家怎么通過MyBatis插件自動生成mapper對應(yīng)的文件和對應(yīng)的bean文件笋熬。使用起來非常簡單碱璃。

? ? ? ?第一步计济,在pom.xml文件里面添加plugin。這里要注意configurationFile部分這個字段指明generatorConfig.xml文件的位置各吨。generatorConfig.xml在第二步會教大家怎么配置撩满。這里我們指定的目錄是resources/generator文件夾下面,大家根據(jù)自己的實(shí)際情況來指定绅你。

            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>5.1.35</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <!--配置文件的路徑-->
                    <configurationFile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>

? ? ? ?第二步伺帘,generatorConfig.xml文件的配置,主要改的地方就是jdbcConnection字段里面數(shù)據(jù)庫相關(guān)的信息忌锯。以及javaModelGenerator伪嫁,sqlMapGenerator,javaClientGenerator字段目標(biāo)文件的位置偶垮。和table字段里面改成自己的表格张咳。關(guān)于這些東西generatorConfig.xml文件里面咱們也注釋的很清楚。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!--執(zhí)行命令 mvn mybatis-generator:generate-->
    <context id="test" targetRuntime="MyBatis3">
        <plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin"></plugin>
        <plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin>
        <plugin type="org.mybatis.generator.plugins.ToStringPlugin"></plugin>
        <commentGenerator>
            <!-- 這個元素用來去除指定生成的注釋中是否包含生成的日期 false:表示保護(hù) -->
            <!-- 如果生成日期似舵,會造成即使修改一個字段脚猾,整個實(shí)體類所有屬性都會發(fā)生變化,不利于版本控制砚哗,所以設(shè)置為true -->
            <property name="suppressDate" value="true"/>
            <!-- 是否去除自動生成的注釋 true:是 : false:否 -->
            <property name="suppressAllComments" value="false"/>
        </commentGenerator>
        <!--數(shù)據(jù)庫鏈接URL龙助,用戶名、密碼 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://192.168.13.98/dcim" userId="root" password="123456">
        </jdbcConnection>
        <javaTypeResolver>
            <!-- This property is used to specify whether MyBatis Generator should
                force the use of java.math.BigDecimal for DECIMAL and NUMERIC fields, -->
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!-- 生成模型的包名和位置 -->
        <javaModelGenerator targetPackage="com.pilot.dcim.alarmmanage.entity.model"
                            targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- 生成映射文件的包名和位置 -->
        <sqlMapGenerator targetPackage="com.pilot.dcim.alarmmanage.mapper"
                         targetProject="src/main/resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- 生成DAO的包名和位置 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.pilot.dcim.alarmmanage.mapper"
                             implementationPackage="com.pilot.dcim.alarmmanage.service.impl"
                             targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>

        <!-- 要生成哪些表 -->
        <table tableName="alarmgroup" domainObjectName="AlarmGroup"
               enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="false"
               selectByExampleQueryId="false"></table>
        <table tableName="alarmparam" domainObjectName="AlarmParam"
               enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="false"
               selectByExampleQueryId="false"></table>
        <table tableName="alarmsetting" domainObjectName="AlarmSetting"
               enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="false"
               selectByExampleQueryId="false"></table>
        <table tableName="faultevent" domainObjectName="FaultEvent"
               enableCountByExample="false" enableUpdateByExample="false"
               enableDeleteByExample="false" enableSelectByExample="false"
               selectByExampleQueryId="false"></table>
    </context>
</generatorConfiguration>

? ? ? ?第三步蛛芥,上面兩部都配置好之后提鸟,執(zhí)行命令 mvn mybatis-generator:generate 就會在對應(yīng)的目錄下生成我們想要的文件军援。


? ? ? ?MyBatis的動態(tài)SQL是基于OGNL的表達(dá)式的。它對SQL語句進(jìn)行靈活的操作称勋。通過表達(dá)式判斷來實(shí)現(xiàn)對SQL的靈活拼接胸哥、組裝。我們著重講說MyBatis動態(tài)SQL里面一些元素的使用赡鲜。

一空厌、MyBatis動態(tài)SQL標(biāo)簽的學(xué)習(xí)

1.1、if 條件判斷標(biāo)簽

? ? ? ?if標(biāo)簽通用用于通過判斷參數(shù)值來決定是否使用某個查詢條件银酬。

1.1.1嘲更、if 判斷數(shù)字

? ? ? ?if 判斷數(shù)字,大部分都是判斷等于或者不等于某個數(shù)字捡硅。

<if test="filter == 1">
    ...
</if>

1.1.2哮内、if 判斷字符串

? ? ? ?大部分情況下都是去判斷傳遞過來的字符串是否為空。當(dāng)然咱們也是可以添加別的條件限制的壮韭,比如以啥字符串開頭北发,以啥字符串結(jié)尾。

1.1.2.1喷屋、判斷字符串是否為空,或者字符串等于某個值

    <select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">
        select * from user
        <where>
            <if test="user.name != null and user.name == '0'.toString()">
                and name = #{user.name}
            </if>

        </where>

    </select>

1.1.2.2琳拨、判斷字符串是否包含

    <select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">
        select * from user
        <where>
            <if test=" user.name != null and user.name.contains('1'.toString())">
                and name = #{user.name}
            </if>

        </where>

    </select>

1.1.2.3、判斷是否以字符串開頭

    <select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">
        select * from user
        <where>
            <if test=" user.name != null and user.name.startsWith('1'.toString())">
                and name = #{user.name}
            </if>

        </where>

    </select>

1.1.3屯曹、判斷列表

? ? ? ?經(jīng)常判斷列表是否為null狱庇,或者列表是否為空。列表判斷也是很簡單的直接 <if test=" nameList != null and nameList.size() > 0 "> 就搞定了恶耽。

一個簡單的實(shí)例密任,通過用戶名(list)查詢用戶

    List<User> selectUserByName(@Param("nameList") List<String> nameList);
    <!-- 通過用戶名查找用戶 -->
    <select id="selectUserByName" resultType="com.tuacy.mybatisdemo.model.User">
        select * from user
        <where>
            <if test=" nameList != null and nameList.size() > 0 ">
                <trim prefix=" name in ">
                    <foreach collection="nameList" item="i" index="index" open="(" separator="," close=")">
                        <if test="i != null">
                            #{i}
                        </if>
                    </foreach>
                </trim>
            </if>

        </where>

    </select>

1.2、choose偷俭,when浪讳,otherwise標(biāo)簽(switch case)

? ? ? ?choose,when涌萤,otherwise標(biāo)簽的作用類似與咱們java里面的switch case的作用淹遵。

<choose>
    <when test="item.name != null">
        #{item.name,jdbcType=VARCHAR},
    </when>
    <otherwise>
        null,
    </otherwise>
</choose>

1.3、foreach循環(huán)標(biāo)簽

? ? ? ?foreach的主要用在構(gòu)建in條件中负溪,它可以在SQL語句中進(jìn)行迭代一個集合透揣。大部分都是對一個list進(jìn)行循環(huán)。

? ? ? ?foreach元素的屬性主要有 item川抡,index辐真,collection,open,separator拆祈,close恨闪。

foreach元素 解釋
collection 迭代的對象
item 迭代過程中的每個元素
index 迭代過程中的位置
open 語句以什么開始
separator 語句以什么作為分隔符
close 語句以什么結(jié)束

? ? ? ?在使用foreach的時候最關(guān)鍵的也是最容易出錯的就是collection屬性倘感,該屬性是必須指定的放坏,但是在不同情況 下,該屬性的值是不一樣的老玛,主要有一下3種情況:

    1. 如果傳入的是單參數(shù)且參數(shù)類型是一個List的時候淤年,collection屬性值為list。
    1. 如果傳入的是單參數(shù)且參數(shù)類型是一個array數(shù)組的時候蜡豹,collection的屬性值為array麸粮。
    1. 如果傳入的參數(shù)是多個的時候,我們就需要把它們封裝成一個Map了镜廉,當(dāng)然單參數(shù)也可以弄诲。

一個簡單的實(shí)例

<select id="dynamicForeachTest" parameterType="java.util.List" resultType="Blog">
          select * from t_blog where id in
        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
                #{item}       
        </foreach>    
    </select>

array

<select id="dynamicForeach2Test" parameterType="java.util.ArrayList" resultType="Blog">
     select * from t_blog where id in
     <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
          #{item}
     </foreach>
 </select>   

map

<select id="dynamicForeach3Test" parameterType="java.util.HashMap" resultType="Blog">
         select * from t_blog where title like "%"#{title}"%" and id in
          <foreach collection="ids" index="index" item="item" open="(" separator="," close=")">
               #{item}
          </foreach>
 </select>

上面說的都是沒有指定@Param的情況,如果指定了@Param則collection的屬性值是@Param指定的名字娇唯。

1.4齐遵、trim標(biāo)簽

? ? ? ?trim標(biāo)記是一個格式化的標(biāo)記,可以完成set或者是where標(biāo)記的功能塔插。

trim屬性 描述
prefix 給sql語句拼接的前綴
suffix 給sql語句拼接的后綴
prefixesToOverride 去除sql語句前面的關(guān)鍵字或者字符梗摇,該關(guān)鍵字或者字符由prefixesToOverride屬性指定,假設(shè)該屬性指定為”AND”想许,當(dāng)sql語句的開頭為”AND”伶授,trim標(biāo)簽將會去除該”AND
suffixesToOverride 去除sql語句后面的關(guān)鍵字或者字符,該關(guān)鍵字或者字符由suffixesToOverride屬性指定
<trim prefix="WHERE" prefixOverrides="AND">
    <if test="state != null">
      state = #{state}
    </if> 
    <if test="title != null">
      AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
      AND author_name like #{author.name}
    </if>
</trim>

1.5流纹、where標(biāo)簽

? ? ? ?where標(biāo)簽是非常有用的糜烹,他有兩個作用:

  • 當(dāng)where標(biāo)簽里面元素的元素都不滿足條件的時候,不會插入where語句漱凝。
  • where標(biāo)簽里面若語句的開頭為“AND”或“OR”疮蹦,where 元素也會將它們?nèi)コ?/li>

有這么一個例子,我呢有一個user表(pkid, name, phone, password)碉哑,現(xiàn)在根據(jù)我們傳入的條件來查詢user信息挚币。

    <!-- 查找指定的用戶 -->
    <select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">
        select * from user
        <where>
            <if test="user.pkid != null">
                pkid = #{user.pkid}
            </if>

            <if test="user.name != null">
                and name = #{user.name}
            </if>

            <if test="user.phone != null">
                and phone = #{user.phone}
            </if>

            <if test="user.password != null">
                and password = #{user.password}
            </if>

        </where>

    </select>

1.6、set標(biāo)簽

? ? ? ?set標(biāo)簽和where標(biāo)簽一樣扣典。會自動加上set關(guān)鍵字妆毕,并且去掉不必要的一些字符。

<set>   
    <if test="userId !=null and userId !=''">    
        AND A.userId = #{userId,jdbcType=CHAR}    
    </if>    
    <if test="userName !=null and userName !=''">    
        AND A.userName = #{userName,jdbcType=CHAR}    
    </if>   
</set>  

1.7贮尖、bind標(biāo)簽

? ? ? ?bind 標(biāo)簽可以使用 OGNL 表達(dá)式創(chuàng)建一個變量井將其綁定到上下文中笛粘。咱就可以簡單的認(rèn)為是聲明了一個變量。

這個例子里面,我純粹的是把user.name替換成了user.name了薪前。

    <select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">
        select * from user
        <where>
            <bind name="userName" value="user.name"/>
            <if test=" userName != null ">
                and name = #{userName}
            </if>

        </where>

    </select>

這例子里面咱用bind標(biāo)簽聲明了一個模糊查詢的變量

    <select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">
        select * from user
        <where>
            <bind name="patternName" value="'%' + user.name + '%'" />
            <if test=" user.name != null ">
                and name like #{patternName}
            </if>

        </where>

    </select>

二润努、MyBatis動態(tài)SQL實(shí)例

? ? ? ?最后我們根據(jù)今天所學(xué)到的內(nèi)容,給出兩個比較復(fù)雜的MyBats動態(tài)SQL示括。

2.1铺浇、批量插入并且更新主鍵

    <!-- 批量插入并且更新主鍵 -->
    <insert id="insertUserBatch" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="pkid">
        insert into user (name, password, phone)
        values
        <foreach collection="list" item="item" index="index" separator=",">
            <trim prefix="(" suffix=")" suffixOverrides=",">
                <choose>
                    <when test="item.name != null">
                        #{item.name,jdbcType=VARCHAR},
                    </when>
                    <otherwise>
                        null,
                    </otherwise>
                </choose>
                <choose>
                    <when test="item.password != null">
                        #{item.password,jdbcType=VARCHAR},
                    </when>
                    <otherwise>
                        null,
                    </otherwise>
                </choose>
                <choose>
                    <when test="item.phone != null">
                        #{item.phone,jdbcType=VARCHAR},
                    </when>
                    <otherwise>
                        null,
                    </otherwise>
                </choose>
            </trim>
        </foreach>
    </insert>

2.2、批量更新

   <!-- 批量更新 -->
    <update id="updateUserBatch" parameterType="java.util.List">
        update user
        <trim prefix="set" suffixOverrides=",">
            <trim prefix="name =case" suffix="end,">
                <foreach collection="list" item="i" index="index">
                    <if test="i.name!=null">
                        when pkid=#{i.pkid} then #{i.name}
                    </if>
                </foreach>
            </trim>
            <trim prefix=" password =case" suffix="end,">
                <foreach collection="list" item="i" index="index">
                    <if test="i.password!=null">
                        when pkid=#{i.pkid} then #{i.password}
                    </if>
                </foreach>
            </trim>

            <trim prefix="phone =case" suffix="end,">
                <foreach collection="list" item="i" index="index">
                    <if test="i.phone!=null">
                        when pkid=#{i.pkid} then #{i.phone}
                    </if>
                </foreach>
            </trim>
        </trim>
        where
        <foreach collection="list" separator="or" item="i" index="index">
            pkid=#{i.pkid}
        </foreach>
    </update>

? ? ? ?上面涉及到的所有實(shí)例的下載地址:https://github.com/tuacy/mybatisdemo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末垛膝,一起剝皮案震驚了整個濱河市鳍侣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吼拥,老刑警劉巖倚聚,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異凿可,居然都是意外死亡惑折,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進(jìn)店門枯跑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惨驶,“玉大人,你說我怎么就攤上這事全肮〕ㄟ郑” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵辜腺,是天一觀的道長休建。 經(jīng)常有香客問我,道長评疗,這世上最難降的妖魔是什么测砂? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮百匆,結(jié)果婚禮上砌些,老公的妹妹穿的比我還像新娘。我一直安慰自己加匈,他們只是感情好存璃,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著雕拼,像睡著了一般纵东。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上啥寇,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天偎球,我揣著相機(jī)與錄音洒扎,去河邊找鬼。 笑死衰絮,一個胖子當(dāng)著我的面吹牛袍冷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播猫牡,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼胡诗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了镊掖?” 一聲冷哼從身側(cè)響起乃戈,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤褂痰,失蹤者是張志新(化名)和其女友劉穎亩进,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缩歪,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡归薛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了匪蝙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片主籍。...
    茶點(diǎn)故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖逛球,靈堂內(nèi)的尸體忽然破棺而出千元,到底是詐尸還是另有隱情,我是刑警寧澤颤绕,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布幸海,位于F島的核電站,受9級特大地震影響奥务,放射性物質(zhì)發(fā)生泄漏物独。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一氯葬、第九天 我趴在偏房一處隱蔽的房頂上張望挡篓。 院中可真熱鬧,春花似錦帚称、人聲如沸官研。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽戏羽。三九已至,卻和暖如春瞻坝,著一層夾襖步出監(jiān)牢的瞬間蛛壳,已是汗流浹背杏瞻。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衙荐,地道東北人捞挥。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像忧吟,于是被迫代替她去往敵國和親砌函。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評論 2 359

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