首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

MyBatis Mapper XML SQL 報錯:字串字面量用單引號、變數用 #{}

     編輯:程式設計疑難解答

錯誤現場

Mapper XML 中:

<select id="findByStatus" resultType="User">
    SELECT * FROM user WHERE status = ""  -- 錯誤:雙引號或空字串
</select>

控制台報錯:SQL 語法錯誤、參數綁定失敗。

根因

  • 固定值字串字面量必須用單引號:status = '1'、name = 'admin'。
  • 動態參數必須用 #{paramName}:status = #{statusId},MyBatis 會生成 ? 佔位符並設定 PreparedStatement 參數,防 SQL 注入、自動處理型別轉換。
  • ${paramName} 是字串直接替換(如 ORDER BY ${col}),**極度危險**,僅用於不可參數化的 SQL 片段(表名、欄位名、排序方向),且必須嚴格白名單驗證。

修正範例

<!-- 固定值查詢 -->
<select id="findActiveUsers" resultType="User">
    SELECT * FROM user WHERE status = '1' AND deleted = '0'
</select>

<!-- 動態參數查詢 -->
<select id="findByStatus" resultType="User">
    SELECT * FROM user WHERE status = #{statusId}
</select>

<!-- 多條件動態 SQL -->
<select id="searchUsers" resultType="User">
    SELECT * FROM user
    <where>
        <if test="name != null and name != ''">
            AND name LIKE CONCAT('%', #{name}, '%')
        </if>
        <if test="status != null">
            AND status = #{status}
        </if>
    </where>
    ORDER BY create_time DESC
</select>

常見錯誤對照表

寫法結果適用場景
status = '1'正確固定字串/數值字面量
status = "1"錯誤(MySQL 模式下雙引號為識別符)—
status = #{status}正確動態參數(預處理語句)
status = ${status}危險(字串拼接,注入風險)僅用於表名/欄位名/排序
status = ''語法合法但邏輯錯(查空字串)—

最佳實踐

  1. **預設用 #{}**,除非確定需要動態 SQL 結構(表名、欄位名)。
  2. 固定值直接寫在 SQL 中('1', 100),別用 #{} 傳常數(增加參數綁定開銷)。
  3. 啟用 MyBatis 日誌(log4j.logger.org.apache.ibatis=DEBUG),觀察生成的 PreparedStatement 與參數值。
  4. 用 <where>, <if>, <trim> 構建動態條件,避免手工拼接 AND/OR 導致語法錯誤。

總結: Mapper XML 中,**固定值用單引號 'val',變數用 #{var}**。雙引號、空字串、${} 濫用是新手最常見的 SQL 語法/注入 Bug 來源。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved