在以前的CRUD例子中,都是一些很簡單的SQL,然而實際的業務開發中會有一些複雜的SQL,咱們常常須要拼接SQL,拼接的時候要確保不能忘了必要的空格,還要注意省掉列名列表最後的逗號。Mybatis個一個強大特性--動態SQL,這一特性能夠完全擺脫這種痛苦。html
如今有以下查詢:spring
<!-- 根據條件查詢用戶 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> SELECT id, username, birthday, sex, address FROM `user` WHERE sex = #{sex} AND username LIKE '%${username}%' </select>
當咱們帶入兩個參數時,返回結果不會有問題,但是當咱們只帶入姓名,不帶入性別時,結果就不合理,由於sex帶入的null,做爲查詢條件就過濾告終果,這個時候咱們須要if標籤。sql
改造sql:數組
<!-- 根據條件查詢用戶 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> SELECT id, username, birthday, sex, address FROM `user` WHERE 1=1 <if test="sex!=null and sex !=''"> AND sex = #{sex} </if> <if test="username!=null and username!=''"> AND username like '%${username}%' </if> </select>
將接口和方法都加入其中mybatis
@Test public void testQueryUserByWhere() { // mybatis和spring整合,整合以後,交給spring管理 SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 建立Mapper接口的動態代理對象,整合以後,交給spring管理 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 使用userMapper執行根據條件查詢用戶 User user = new User(); //user.setSex("1"); user.setUsername("張"); List<User>list = userMapper.queryUserByWhere(user); for (User u : list) { System.out.println(u); } // mybatis和spring整合,整合以後,交給spring管理 sqlSession.close(); }
結果:app
where標籤會把第一個and忽略,固然若是是or開頭的,MyBatis也會把它忽略,此外,在where元素中你不須要考慮空格的問題,MyBatis會智能的幫你加上。ide
<select id="queryUserByWhere1" parameterType="user" resultType="user"> SELECT id, username, birthday, sex, address FROM `user` <!-- where標籤能夠自動添加where,同時處理sql語句中第一個and或者or關鍵字 --> <where> <if test="sex!=null"> AND sex = #{sex} </if> <if test="username!=null and username!=''"> AND username like '%${username}%' </if> </where> </select>
在更新的時候咱們也須要像where同樣可以進行動態判斷,這個時候就使用set標籤,set會使最後的逗號忽略,咱們就能夠動態的更新那些修改了的字段。測試
以下:this
<update id="dynamicSetTest" parameterType="user"> update `user` <set> <if test="sex != null"> sex = #{sex}, </if> <if test="username!=null and username!=''"> username = #{username}, </if> </set> where id = #{id} </update>
測試:spa
@Test public void dynamicSetTest() { SqlSession sqlSession = this.sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); //user.setSex("1"); user.setUsername("袁大大"); user.setId(26); userMapper.dynamicSetTest(user); sqlSession.commit(); sqlSession.close(); }
choose的做用相似Java語言中的switch,能夠解決咱們只想選擇一個查詢條件的狀況。
以下:
<select id="selectUserByChoose" resultType="user" parameterType="user"> select id, username, birthday, sex, address FROM `user` <where> <choose> <when test="id !='' and id != null"> id=#{id} </when> <when test="username !='' and username != null"> and username like #{username} </when> <otherwise> and sex=#{sex} </otherwise> </choose> </where> </select>
這個寫法很容易理解,與switch相同,匹配成功後就會跳出。
trim標記是一個格式化的標記,能夠完成set或者是where標記的功能,怎麼用呢:
增長prefix前綴,去掉第一個prefixoverride中內容。
增長suffix後綴,去掉最後一個suffixoverride中內容。
經過trim能夠解決where 與set 問題
<select id="selectUserByUsernameAndSex" resultType="user" parameterType="user"> select * from user <!-- <where> <if test="username != null"> username=#{username} </if> <if test="username != null"> and sex=#{sex} </if> </where> --> <trim prefix="where" prefixOverrides="and | or"> <if test="username != null"> and username=#{username} </if> <if test="sex != null"> and sex=#{sex} </if> </trim> </select>
先增長where,並去掉第一個and 或者or ,替換了where if 寫法。
<!-- 根據 id 更新 user 表的數據 --> <update id="updateUserById" parameterType="com.ys.po.User"> update user u <!-- <set> <if test="username != null and username != ''"> u.username = #{username}, </if> <if test="sex != null and sex != ''"> u.sex = #{sex} </if> </set> --> <trim prefix="set" suffixOverrides=","> <if test="username != null and username != ''"> u.username = #{username}, </if> <if test="sex != null and sex != ''"> u.sex = #{sex}, </if> </trim> where id=#{id} </update>
增長set,並去掉最後一個逗號,替換了set if寫法。
寫sql時常常會出現一些重複片斷,咱們能夠進行提取,這樣能夠作到重用。
先使用sql進行聲明:
<!-- 聲明sql片斷 --> <sql id="userFields"> id, username, birthday, sex, address </sql>
使用include refid:
<select id="queryUserBySqlWhere" parameterType="user" resultType="user"> <!-- SELECT id, username, birthday, sex, address FROM `user` --> <!-- 使用include標籤加載sql片斷;refid是sql片斷id --> SELECT <include refid ="userFields"/> FROM `user` <!-- where標籤能夠自動添加where關鍵字,同時處理sql語句中第一個and關鍵字 --> <where> <if test="sex != null"> AND sex = #{sex} </if> <if test="username != null and username != ''"> AND username LIKE '%${username}%' </if> </where> </select>
當咱們向sql傳遞數組或List,mybatis使用foreach解析。
foreach標籤,進行遍歷
collection:遍歷的集合,這裏是QueryVo的ids屬性
item:遍歷的項目,能夠隨便寫,,可是和後面的#{}裏面要一致
open:在前面添加的sql片斷
close:在結尾處添加的sql片斷
separator:指定遍歷的元素之間使用的分隔符
<select id="queryUserByIds" parameterType="com.yuanqinnan.pojo.QueryVo" resultType="user"> SELECT * FROM `user` <where> <foreach collection="ids" item="item" open="id IN (" close=")" separator=","> #{item} </foreach>
改造QueryVo:
@Data public class QueryVo { private User user; private List<Integer> ids; }
測試方法:
@Test public void queryUserByIds(){ SqlSession sqlSession = this.sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); QueryVo user = new QueryVo(); List<Integer>ids = new ArrayList<>(); ids.add(1); ids.add(10); ids.add(24); user.setIds(ids); List<User> list = userMapper.queryUserByIds(user); for (User u : list) { System.out.println(u); } sqlSession.close(); }
結果
動態sql實際上是一個拼接過程,咱們掌握上面這些標籤,就能完成mybatis的動態sql
原文出處:https://www.cnblogs.com/yuanqinnan/p/10712679.html