MyBatis踩坑之單字符條件比較

背景

Mybatis中可以使用 <choose><when>...</when></choose> 語句來實現條件選擇,<when> 標籤含有 test 屬性用於設置比較條件,但是在某些特定情況下,字符串的比較會存在一個坑,那就是單字符字符串會被降級爲字符類型(char),從而導致比較條件不會生效。

示例

假設有如下需求:用戶分爲個人賬戶和機構賬戶兩類,其中個人賬戶使用身份證註冊,機構用戶使用機構統一社會信用代碼註冊,某個功能需要提供根據用戶類型(個人/機構)以及對應的證件號碼查詢用戶信息。

1. 數據庫

CREATE TABLE `t_user` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
  `username` varchar(50) NOT NULL COMMENT '用戶名',
  `user_type` varchar(1) NOT NULL COMMENT '用戶類型(0-個人用戶,1-機構用戶)',
  `user_id` varchar(18) DEFAULT NULL COMMENT '個人用戶身份證',
  `org_id` varchar(18) DEFAULT NULL COMMENT '企業用戶機構代碼',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

2. 對應的MyBatis Mapper文件

 <select id="getUser" resultMap="UserMap">
    SELECT
    <include refid="base_columns" />
    FROM t_user
    WHERE 1=1
    AND user_type = #{userType,jdbcType=VARCHAR}
    <choose>
        <when test="userType == '0'">
            AND user_id = #{userId,jdbcType=VARCHAR}
        </when>
        <when test="userType == '1'">
            AND org_id = #{orgId,jdbcType=VARCHAR}
        </when>
    </choose>
</select>

接口調用:

User user = userMapper.getUser("0", "310109196509080012", null);

跑單元測試發現報錯:

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3

檢查SQL語句調用,發現 <when> 中定義的 AND 連接條件根本沒有生效:

SELECT id, username, user_type, user_id, org_id, create_time, update_time FROM t_user WHERE 1=1 AND user_type = ?

3. 解決方案

解決方案有兩種,一是把 <when> 中條件語句等號右邊的字符串改爲整數,二是把條件語句等號右邊的字符串加上 .toString() 方法調用。

修改後再次運行單元測試,測試通過,輸出的SQL語句如下:

SELECT id, username, user_type, user_id, org_id, create_time, update_time FROM t_user WHERE 1=1 AND user_type = ? AND user_id = ?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章