MyBatis從入門到精通(六):MyBatis動態Sql之if標籤的用法

最近在讀劉增輝老師所著的《MyBatis從入門到精通》一書,頗有收穫,因而將本身學習的過程以博客形式輸出,若有錯誤,歡迎指正,如幫助到你,不勝榮幸!java

本篇博客主要講解如何使用if標籤生成動態的Sql,主要包含如下3個場景:mysql

  1. 根據查詢條件實現動態查詢
  2. 根據參數值實現動態更新某些列
  3. 根據參數值實現動態插入某些列

1. 使用if標籤實現動態查詢

假設有這樣1個需求:根據用戶的輸入條件來查詢用戶列表,若是輸入了用戶名,就根據用戶名模糊查詢,若是輸入了郵箱,就根據郵箱精確查詢,若是同時輸入了用戶名和郵箱,就用這兩個條件去匹配用戶。git

首先,咱們在接口SysUserMapper中添加以下方法:github

/** * 根據動態條件查詢用戶信息 * * @param sysUser * @return */
List<SysUser> selectByUser(SysUser sysUser);
複製代碼

而後在對應的SysUserMapper.xml中添加以下代碼:sql

<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標籤的test屬性必填,該屬性值是一個符合OGNL要求的判斷表達式,通常只用true或false做爲結果。mybatis

2)判斷條件property != null 或 property == null,適用於任何類型的字段,用於判斷屬性值是否爲空。app

3)判斷條件property != '' 或 property == '',僅適用於String類型的字段,用於判斷是否爲空字符串。學習

4)當有多個判斷條件時,使用and或or進行鏈接,嵌套的判斷可使用小括號分組,and至關於Java中的與(&&),or相關於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);

        // 同時按用戶民和郵箱查詢
        query = new SysUser();
        query.setUserName("ad");
        query.setUserEmail("test@mybatis.tk");
        sysUserList = sysUserMapper.selectByUser(query);
        // 因爲沒有同時符合這兩個條件的用戶,所以查詢結果數爲0
        Assert.assertTrue(sysUserList.size() == 0);
    } finally {
        sqlSession.close();
    }
}
複製代碼

運行測試代碼,測試經過,輸出日誌以下:

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標籤實現動態更新

假設有這樣1個需求:更新用戶信息的時候不能將原來有值但沒有發生變化的字段更新爲空或null,即只更新有值的字段。

首先,咱們在接口SysUserMapper中添加以下方法:

/** * 根據主鍵選擇性更新用戶信息 * * @param sysUser * @return */
int updateByIdSelective(SysUser sysUser);
複製代碼

而後在對應的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();
    }
}
複製代碼

運行測試代碼,測試經過,輸出日誌以下:

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標籤實現動態插入

假設有這樣1個需求:往數據庫表中插入數據的時候,若是某一列的參數值不爲空,就使用傳入的值,若是傳入的參數值爲空,就使用數據庫中的默認值(一般是空),而不使用傳入的空值。

爲了更好的理解該示例,咱們先給sys_user表的user_email字段設置默認值:test@mybatis.tk,Sql語句以下:

ALTER TABLE sys_user
MODIFY COLUMN user_email VARCHAR(50) NULL DEFAULT  'test@mybatis.tk'
COMMENT '郵箱'
AFTER user_password;
複製代碼

首先,咱們在接口SysUserMapper中添加以下方法:

/** * 根據傳入的參數值動態插入列 * * @param sysUser * @return */
int insertSelective(SysUser sysUser);
複製代碼

而後在對應的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);

        // 獲取剛剛插入的數據
        sysUser = sysUserMapper.selectById(sysUser.getId());
        // 由於沒有指定userEmail,因此用的是數據庫的默認值
        Assert.assertEquals("test@mybatis.tk", sysUser.getUserEmail());
    } finally {
        sqlSession.close();
    }
}
複製代碼

運行測試代碼,測試經過,輸出日誌以下:

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. 源碼

源碼地址:github.com/zwwhnly/myb…,歡迎下載。

5. 參考

劉增輝《MyBatis從入門到精通》

相關文章
相關標籤/搜索