MyBatis動態SQL

? ? ? ?在講MyBatis動態SQL之前,先教大家怎么通過MyBatis插件自動生成mapper對應的文件和對應的bean文件。使用起來非常簡單。

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

            <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字段里面數據庫相關的信息。以及javaModelGenerator,sqlMapGenerator,javaClientGenerator字段目標文件的位置。和table字段里面改成自己的表格。關于這些東西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>
    <!--執行命令 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:表示保護 -->
            <!-- 如果生成日期,會造成即使修改一個字段,整個實體類所有屬性都會發生變化,不利于版本控制,所以設置為true -->
            <property name="suppressDate" value="true"/>
            <!-- 是否去除自動生成的注釋 true:是 : false:否 -->
            <property name="suppressAllComments" value="false"/>
        </commentGenerator>
        <!--數據庫鏈接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>

? ? ? ?第三步,上面兩部都配置好之后,執行命令 mvn mybatis-generator:generate 就會在對應的目錄下生成我們想要的文件。


? ? ? ?MyBatis的動態SQL是基于OGNL的表達式的。它對SQL語句進行靈活的操作。通過表達式判斷來實現對SQL的靈活拼接、組裝。我們著重講說MyBatis動態SQL里面一些元素的使用。

一、MyBatis動態SQL標簽的學習

1.1、if 條件判斷標簽

? ? ? ?if標簽通用用于通過判斷參數值來決定是否使用某個查詢條件。

1.1.1、if 判斷數字

? ? ? ?if 判斷數字,大部分都是判斷等于或者不等于某個數字。

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

1.1.2、if 判斷字符串

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

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、判斷列表

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

一個簡單的實例,通過用戶名(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標簽(switch case)

? ? ? ?choose,when,otherwise標簽的作用類似與咱們java里面的switch case的作用。

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

1.3、foreach循環標簽

? ? ? ?foreach的主要用在構建in條件中,它可以在SQL語句中進行迭代一個集合。大部分都是對一個list進行循環。

? ? ? ?foreach元素的屬性主要有 item,index,collection,open,separator,close。

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

? ? ? ?在使用foreach的時候最關鍵的也是最容易出錯的就是collection屬性,該屬性是必須指定的,但是在不同情況 下,該屬性的值是不一樣的,主要有一下3種情況:

    1. 如果傳入的是單參數且參數類型是一個List的時候,collection屬性值為list。
    1. 如果傳入的是單參數且參數類型是一個array數組的時候,collection的屬性值為array。
    1. 如果傳入的參數是多個的時候,我們就需要把它們封裝成一個Map了,當然單參數也可以。

一個簡單的實例

<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標簽

? ? ? ?trim標記是一個格式化的標記,可以完成set或者是where標記的功能。

trim屬性 描述
prefix 給sql語句拼接的前綴
suffix 給sql語句拼接的后綴
prefixesToOverride 去除sql語句前面的關鍵字或者字符,該關鍵字或者字符由prefixesToOverride屬性指定,假設該屬性指定為”AND”,當sql語句的開頭為”AND”,trim標簽將會去除該”AND
suffixesToOverride 去除sql語句后面的關鍵字或者字符,該關鍵字或者字符由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標簽

? ? ? ?where標簽是非常有用的,他有兩個作用:

  • 當where標簽里面元素的元素都不滿足條件的時候,不會插入where語句。
  • where標簽里面若語句的開頭為“AND”或“OR”,where 元素也會將它們去除。

有這么一個例子,我呢有一個user表(pkid, name, phone, password),現在根據我們傳入的條件來查詢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標簽

? ? ? ?set標簽和where標簽一樣。會自動加上set關鍵字,并且去掉不必要的一些字符。

<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標簽

? ? ? ?bind 標簽可以使用 OGNL 表達式創建一個變量井將其綁定到上下文中。咱就可以簡單的認為是聲明了一個變量。

這個例子里面,我純粹的是把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標簽聲明了一個模糊查詢的變量

    <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動態SQL實例

? ? ? ?最后我們根據今天所學到的內容,給出兩個比較復雜的MyBats動態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>

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

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容