MyBatis動態(tài)Sql之if標(biāo)簽的用法詳解
最近在讀劉增輝老師所著的《MyBatis從入門到精通》一書,很有收獲,于是將自己學(xué)習(xí)的過程以博客形式輸出,如有錯(cuò)誤,歡迎指正,如幫助到你,不勝榮幸!
本篇博客主要講解如何使用if標(biāo)簽生成動態(tài)的Sql,主要包含以下3個(gè)場景:
1.根據(jù)查詢條件實(shí)現(xiàn)動態(tài)查詢
2.根據(jù)參數(shù)值實(shí)現(xiàn)動態(tài)更新某些列
3.根據(jù)參數(shù)值實(shí)現(xiàn)動態(tài)插入某些列
1. 使用if標(biāo)簽實(shí)現(xiàn)動態(tài)查詢
假設(shè)有這樣1個(gè)需求:根據(jù)用戶的輸入條件來查詢用戶列表,如果輸入了用戶名,就根據(jù)用戶名模糊查詢,如果輸入了郵箱,就根據(jù)郵箱精確查詢,如果同時(shí)輸入了用戶名和郵箱,就用這兩個(gè)條件去匹配用戶。
首先,我們在接口SysUserMapper中添加如下方法:
/** * 根據(jù)動態(tài)條件查詢用戶信息 * * @param sysUser * @return */ List<SysUser> selectByUser(SysUser sysUser);
然后在對應(yīng)的SysUserMapper.xml中添加如下代碼:
<select id="selectByUser" resultType="com.zwwhnly.mybatisaction.model.SysUser"> SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE 1 = 1 <if test="userName != null and userName != ''"> AND user_name LIKE CONCAT('%',#{userName},'%') </if> <if test="userEmail != null and userEmail != ''"> AND user_email = #{userEmail} </if> </select>
代碼簡單講解:
1)if標(biāo)簽的test屬性必填,該屬性值是一個(gè)符合OGNL要求的判斷表達(dá)式,一般只用true或false作為結(jié)果。
2)判斷條件property != null 或 property == null,適用于任何類型的字段,用于判斷屬性值是否為空。
3)判斷條件property != '' 或 property == '',僅適用于String類型的字段,用于判斷是否為空字符串。
4)當(dāng)有多個(gè)判斷條件時(shí),使用and或or進(jìn)行連接,嵌套的判斷可以使用小括號分組,and相當(dāng)于Java中的與(&&),or相關(guān)于Java中的或(||)。
所以上面代碼的意思就是先判斷字段是否為null,然后再判斷字段是否為空字符串。
最后,在SysUserMapperTest測試類中添加如下測試方法:
@Test public void testSelectByUser() { SqlSession sqlSession = getSqlSession(); try { SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class); // 只按用戶名查詢 SysUser query = new SysUser(); query.setUserName("ad"); List<SysUser> sysUserList = sysUserMapper.selectByUser(query); Assert.assertTrue(sysUserList.size() > 0); // 只按郵箱查詢 query = new SysUser(); query.setUserEmail("test@mybatis.tk"); sysUserList = sysUserMapper.selectByUser(query); Assert.assertTrue(sysUserList.size() > 0); // 同時(shí)按用戶民和郵箱查詢 query = new SysUser(); query.setUserName("ad"); query.setUserEmail("test@mybatis.tk"); sysUserList = sysUserMapper.selectByUser(query); // 由于沒有同時(shí)符合這兩個(gè)條件的用戶,因此查詢結(jié)果數(shù)為0 Assert.assertTrue(sysUserList.size() == 0); } finally { sqlSession.close(); } }
運(yùn)行測試代碼,測試通過,輸出日志如下:
DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE 1 = 1 AND user_name LIKE CONCAT('%',?,'%') DEBUG [main] - ==> Parameters: ad(String) TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time TRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0 DEBUG [main] - <== Total: 1 DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE 1 = 1 AND user_email = ? DEBUG [main] - ==> Parameters: test@mybatis.tk(String) TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time TRACE [main] - <== Row: 1001, test, 123456, test@mybatis.tk, 2019-06-27 18:21:07.0 DEBUG [main] - <== Total: 1 DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE 1 = 1 AND user_name LIKE CONCAT('%',?,'%') AND user_email = ? DEBUG [main] - ==> Parameters: ad(String), test@mybatis.tk(String) DEBUG [main] - <== Total: 0
2. 使用if標(biāo)簽實(shí)現(xiàn)動態(tài)更新
假設(shè)有這樣1個(gè)需求:更新用戶信息的時(shí)候不能將原來有值但沒有發(fā)生變化的字段更新為空或null,即只更新有值的字段。
首先,我們在接口SysUserMapper中添加如下方法:
/** * 根據(jù)主鍵選擇性更新用戶信息 * * @param sysUser * @return */ int updateByIdSelective(SysUser sysUser);
然后在對應(yīng)的SysUserMapper.xml中添加如下代碼:
<update id="updateByIdSelective"> UPDATE sys_user SET <if test="userName != null and userName != ''"> user_name = #{userName}, </if> <if test="userPassword != null and userPassword != ''"> user_password = #{userPassword}, </if> <if test="userEmail != null and userEmail != ''"> user_email = #{userEmail}, </if> <if test="userInfo != null and userInfo != ''"> user_info = #{userInfo}, </if> <if test="headImg != null"> head_img = #{headImg,jdbcType=BLOB}, </if> <if test="createTime != null"> create_time = #{createTime,jdbcType=TIMESTAMP}, </if> id = #{id} WHERE id = #{id} </update>
最后,在SysUserMapperTest測試類中添加如下測試方法:
@Test public void testUpdateByIdSelective() { SqlSession sqlSession = getSqlSession(); try { SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class); SysUser sysUser = new SysUser(); // 更新id=1的用戶 sysUser.setId(1L); // 修改郵箱 sysUser.setUserEmail("test@mybatis.tk"); int result = sysUserMapper.updateByIdSelective(sysUser); Assert.assertEquals(1, result); // 查詢id=1的用戶 sysUser = sysUserMapper.selectById(1L); // 修改后的名字保持不變,但是郵箱變成了新的 Assert.assertEquals("admin", sysUser.getUserName()); Assert.assertEquals("test@mybatis.tk", sysUser.getUserEmail()); } finally { sqlSession.close(); } }
運(yùn)行測試代碼,測試通過,輸出日志如下:
DEBUG [main] - ==> Preparing: UPDATE sys_user SET user_email = ?, id = ? WHERE id = ? DEBUG [main] - ==> Parameters: test@mybatis.tk(String), 1(Long), 1(Long) DEBUG [main] - <== Updates: 1 DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE id = ? DEBUG [main] - ==> Parameters: 1(Long) TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time TRACE [main] - <== Row: 1, admin, 123456, test@mybatis.tk, 2019-06-27 18:21:07.0 DEBUG [main] - <== Total: 1
3. 使用if標(biāo)簽實(shí)現(xiàn)動態(tài)插入
假設(shè)有這樣1個(gè)需求:往數(shù)據(jù)庫表中插入數(shù)據(jù)的時(shí)候,如果某一列的參數(shù)值不為空,就使用傳入的值,如果傳入的參數(shù)值為空,就使用數(shù)據(jù)庫中的默認(rèn)值(通常是空),而不使用傳入的空值。
為了更好的理解該示例,我們先給sys_user表的user_email字段設(shè)置默認(rèn)值:test@mybatis.tk,Sql語句如下:
ALTER TABLE sys_user MODIFY COLUMN user_email VARCHAR(50) NULL DEFAULT 'test@mybatis.tk' COMMENT '郵箱' AFTER user_password;
首先,我們在接口SysUserMapper中添加如下方法:
/** * 根據(jù)傳入的參數(shù)值動態(tài)插入列 * * @param sysUser * @return */ int insertSelective(SysUser sysUser);
然后在對應(yīng)的SysUserMapper.xml中添加如下代碼:
<insert id="insertSelective" useGeneratedKeys="true" keyProperty="id"> INSERT INTO sys_user(user_name, user_password, <if test="userEmail != null and userEmail != ''"> user_email, </if> user_info, head_img, create_time) VALUES (#{userName},#{userPassword}, <if test="userEmail != null and userEmail != ''"> #{userEmail}, </if> #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType=TIMESTAMP}) </insert>
最后,在SysUserMapperTest測試類中添加如下測試方法:
@Test public void testInsertSelective() { SqlSession sqlSession = getSqlSession(); try { SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class); SysUser sysUser = new SysUser(); sysUser.setUserName("test-selective"); sysUser.setUserPassword("123456"); sysUser.setUserInfo("test info"); sysUser.setCreateTime(new Date()); sysUserMapper.insertSelective(sysUser); // 獲取剛剛插入的數(shù)據(jù) sysUser = sysUserMapper.selectById(sysUser.getId()); // 因?yàn)闆]有指定userEmail,所以用的是數(shù)據(jù)庫的默認(rèn)值 Assert.assertEquals("test@mybatis.tk", sysUser.getUserEmail()); } finally { sqlSession.close(); } }
運(yùn)行測試代碼,測試通過,輸出日志如下:
DEBUG [main] - ==> Preparing: INSERT INTO sys_user(user_name, user_password, user_info, head_img, create_time) VALUES (?,?, ?,?,?) DEBUG [main] - ==> Parameters: test-selective(String), 123456(String), test info(String), null, 2019-07-08 11:40:36.927(Timestamp) DEBUG [main] - <== Updates: 1 DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, create_time FROM sys_user WHERE id = ? DEBUG [main] - ==> Parameters: 1021(Long) TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time TRACE [main] - <== Row: 1021, test-selective, 123456, test@mybatis.tk, 2019-07-08 11:40:37.0 DEBUG [main] - <== Total: 1
4. 源碼
源碼地址:https://github.com/zwwhnly/mybatis-action.git,歡迎下載。
總結(jié)
以上所述是小編給大家介紹的MyBatis動態(tài)Sql之if標(biāo)簽的用法詳解 ,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
相關(guān)文章
使用maven-assembly-plugin如何打包多模塊項(xiàng)目
這篇文章主要介紹了使用maven-assembly-plugin如何打包多模塊項(xiàng)目,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03Java行為型設(shè)計(jì)模式之外觀設(shè)計(jì)模式詳解
外觀模式為多個(gè)復(fù)雜的子系統(tǒng),提供了一個(gè)一致的界面,使得調(diào)用端只和這個(gè)接口發(fā)生調(diào)用,而無須關(guān)系這個(gè)子系統(tǒng)內(nèi)部的細(xì)節(jié)。本文將通過示例詳細(xì)為大家講解一下外觀模式,需要的可以參考一下2022-11-11Java數(shù)據(jù)結(jié)構(gòu)-HashMap詳解
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)-HashMap,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03關(guān)于網(wǎng)頁報(bào)錯(cuò)404原因以及解決方法
404錯(cuò)誤是網(wǎng)站常見的錯(cuò)誤之一,出現(xiàn)的原因很多,解決方法也有很多種,這篇文章主要給大家介紹了關(guān)于網(wǎng)頁報(bào)錯(cuò)404原因以及解決方法的相關(guān)資料,需要的朋友可以參考下2024-01-01springboot+vue項(xiàng)目從第一行代碼到上線部署全流程
本文詳細(xì)介紹了如何從零開始搭建一個(gè)基于Spring Boot和Vue.js的前后端分離項(xiàng)目,并涵蓋項(xiàng)目需求分析、技術(shù)選型、項(xiàng)目結(jié)構(gòu)設(shè)計(jì)、前后端交互、部署上線等全過程,感興趣的朋友跟隨小編一起看看吧2024-11-11