學習MyBatis 動態(tài) SQL

sql教程介紹SQL MyBatis的強大特性SQL

學習MyBatis 動態(tài) SQL

推薦(免費):sql教程

動態(tài) SQL

mybatis 的強大特性之一便是它的動態(tài) sql。如果你有使用 jdbc 或其它類似框架的經驗,你就能體會到根據不同條件拼接 sql 語句的痛苦。例如拼接時要確保不能忘記添加必要的空格,還要注意去掉列表最后一個列名的逗號。利用動態(tài) sql 這一特性可以徹底擺脫這種痛苦。

雖然在以前使用動態(tài) SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射語句中的強大的動態(tài) SQL 語言得以改進這種情形。

動態(tài) SQL 元素和 JSTL 或基于類似 XML 的文本處理器相似。在 MyBatis 之前的版本中,有很多元素需要花時間了解。MyBatis 3 大大精簡了元素種類,現在只需學習原來一半的元素便可。MyBatis 采用功能強大的基于 OGNL 的表達式來淘汰其它大部分元素。

準備

首先創(chuàng)建User實體類

public class User {     private Integer id;     private String username;     private String userEmail;     private String userCity;     private Integer age;}

創(chuàng)建user表

CREATE TABLE user (   id int(11) NOT NULL AUTO_INCREMENT,   username varchar(255) DEFAULT NULL,     user_email varchar(255) DEFAULT NULL,     user_city varchar(255) DEFAULT NULL,     age int(11) DEFAULT NULL,   PRIMARY KEY (id))

if

定義接口方法

public List<User> findByUser(User user);

接口對應的 Mapper.xml 定義如下所示

<select id="findByUser" resultType="com.example.mybatis.entity.User">     select     id, username, user_email userEmail, user_city userCity, age     from user     where    <if test="username != null and username != ''">         username = #{username}    </if>     <if test="userEmail != null and userEmail != ''">         and user_email = #{userEmail}    </if>     <if test="userCity != null and userCity != ''">         and user_city = #{userCity}    </if></select>

如果if標簽上的test為true,那么if標簽里面的SQL語句將會被拼接。

如果username、userEmail、userCity都不為空,那么SQL將會拼接成如下所示

select id, username, user_email userEmail, user_city userCity, age  from user where username = ? and user_email = ? and user_city = ?

如果只有username不為空,那么SQL將會拼接成如下所示

select id, username, user_email userEmail, user_city userCity, age  from user where username = ?

但是這種方式存在一個缺點,假設此時username為空,userEmail、userCity都不為空。

我們來分析動態(tài) SQL 代碼,現在沒有給 username 賦值,即 username==null,所以 “username=#{username}” 這段代碼不會添加到 SQL 語句中,那么最終拼接好的動態(tài) SQL 是這樣的:

select id, username, user_email userEmail, user_city userCity, age  from user where and user_email = ? and user_city = ?

where 后面直接跟 and,很明顯的語法錯誤,此時應該把緊跟在where后面的and刪掉。為了解決這個問題,可以使用where標簽。

where

將上面的SQL改成如下所示

    <select id="findByUser" resultType="com.example.mybatis.entity.User">         select         id, username, user_email userEmail, user_city userCity, age        from user         <where>             <if test="username != null and username != ''">                 username = #{username}             </if>             <if test="userEmail != null and userEmail != ''">                 and user_email = #{userEmail}             </if>             <if test="userCity != null and userCity != ''">                 and user_city = #{userCity}             </if>         </where>     </select>

如果where標簽里面的if標簽有滿足條件的,那么where標簽就會被拼接成where語句,若if標簽拼接的SQL最前面有and語句,那么這個and將會被刪除。使用這種方法, 會自動刪除SQL中不需要的關鍵字,所以一般 if 標簽和 where 標簽會組合起來使用。

trim

trim標簽中的 prefix和 suffix屬性會被用于生成實際的 SQL 語句,會和標簽內部的語句拼接。

如果語句的前面或后面遇到 prefixOverrides或 suffixOverrides屬性中指定的值,MyBatis 會自動將它們刪除。在指定多個值的時候,別忘了每個值后面都要有一個空格,保證不會和后面的 SQL 連接在一起。

prefix:給拼接的SQL語句加一個前綴

suffix:給拼接的SQL語句加一個后綴

prefixOverrides:拼接的SQL語句前面遇到 prefixOverrides,MyBatis 會自動將它們刪除

suffixOverrides:拼接的SQL語句后面遇到 suffixOverrides,MyBatis 會自動將它們刪除

下面使用trim標簽來實現where標簽的功能

<select id="findByUser" resultType="com.example.mybatis.entity.User">         select         id, username, user_email userEmail, user_city userCity, age         from user        <trim prefix="where" prefixOverrides="and">             <if test="username != null and username != ''">                 username = #{username}            </if>             <if test="userEmail != null and userEmail != ''">                 and user_email = #{userEmail}            </if>             <if test="userCity != null and userCity != ''">                 and user_city = #{userCity}            </if>         </trim>     </select>

如果username為空,userEmail和userCity不為空,那么if 標簽拼接的SQL語句如下所示

and user_email = #{userEmail} and user_city = #{userCity}

因為trim標簽設置了prefixOverrides=”and”,而上面的SQL前面有and語句,所以需要將上面的and語句刪掉,又因為trim標簽設置了prefix=”where”,所以需要在拼接的SQL語句前面加一個where語句

最后trim標簽的SQL語句被拼接成如下所示

where user_email = #{userEmail} and user_city = #{userCity}

choose

有時我們不想應用到所有的條件語句,而只想從中擇其一項。針對這種情況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句。

<select id="findByUser" resultType="com.example.mybatis.entity.User">         select         id, username, user_email userEmail, user_city userCity, age         from user        <where>             <choose>                 <when test="username != null and username != ''">                     username = #{username}                </when>                 <when test="userEmail != null and userEmail != ''">                     and user_email = #{userEmail}                </when>                 <when test="userCity != null and userCity != ''">                     and user_city = #{userCity}                </when>             </choose>         </where>     </select>

set

set 標簽用于 Update 操作,會自動根據參數選擇生成 SQL 語句。

接口定義如下

public int updateUser(User user);

接口對應的 Mapper.xml 定義如下所示

<update id="updateUser" parameterType="com.example.mybatis.entity.User">        update user       <set>            <if test="username != null and username != ''">                username=#{username},           </if>            <if test="userEmail != null and userEmail != ''">                user_email=#{userEmail},           </if>            <if test="userCity != null and userCity != ''">                user_city=#{userCity},           </if>            <if test="age != null">               age=#{age}           </if>        </set>        where id=#{id}    </update>

foreach

foreach 標簽可以迭代生成一系列值

*用于 SQL 的 in 語句 *

接口定義如下所示

public List<User> getUsersByIds(List<Integer> ids);

接口對應的 Mapper.xml 定義如下所示

<!--         Collection: 指定要遍歷的集合             默認情況下                 如果為Collection類型的,key為collection;                 如果為List類型的,key為list                 如果是數組類型,key為array             可以通過@Param("ids")來指定key         item: 將當前遍歷的元素賦值給指定的變量         open: 給遍歷的結果添加一個開始字符         close: 給遍歷的結果添加一個結束字符         separator: 每個元素之間的分隔符     --><select id="getUsersByIds"         resultType="com.example.mybatis.entity.User">     select * from user     where id in    <foreach collection="list" item="id" open="(" close=")" separator=",">         #{id}    </foreach></select>

用于批量插入

接口定義如下所示

public int addUserList(List<User> users);

接口對應的 Mapper.xml 定義如下所示

<insert id="addUserList"         parameterType="com.example.mybatis.entity.User">     insert into user     (username, user_email, user_city, age)     values    <foreach item="user"  collection="list" separator=",">         (#{user.username}, #{user.userEmail}, #{user.userCity}, #{user.age})    </foreach></insert><!--返回自增主鍵--><insert id="addUserList"         parameterType="com.example.mybatis.entity.User"         useGeneratedKeys="true"         keyProperty="id">     insert into user     (username, user_email, user_city, age)     values    <foreach item="user"  collection="list" separator=",">         (#{user.username}, #{user.userEmail}, #{user.userCity}, #{user.age})    </foreach></insert><!--還可以這樣寫--><!--     這種方式需要數據庫連接屬性設置allowMultiQueries=true     這種分號分隔多個SQL還可以用于其他的批量操作,如修改、刪除 --><insert id="addUserList"         parameterType="com.example.mybatis.entity.User">     <foreach item="user"  collection="list" separator=";">         insert into user         (username, user_email, user_city, age)         values         (#{user.username}, #{user.userEmail}, #{user.userCity}, #{user.age})    </foreach></insert><!--如果是Oracle數據庫,則需要這樣寫--><insert id="addUserList"         parameterType="com.example.mybatis.entity.User">     <foreach item="user" open="begin" close="end;"  collection="list">         insert into user         (username, user_email, user_city, age)         values         (#{user.username}, #{user.userEmail}, #{user.userCity}, #{user.age});    </foreach></insert>

? 版權聲明
THE END
喜歡就支持一下吧
點贊13 分享