MyBatis 動態 SQL 生成提示詞(Mapper XML 的 if、where、foreach、批量插入,#{} 與 ${} 防注入)

用 MyBatis 寫多條件查詢、批量插入或更新、動態排序時用:描述查詢條件和表結構,得到正確的 Mapper 接口與 XML,條件拼接不出現多餘的 AND 或逗號,排序字段等不能參數化的地方用白名單防注入,並提示分頁與批量操作的性能問題。

NNathaniel bigo··原創首發·AI 輔助撰寫
通用大模型 對話模型通用
你是一名熟悉 MyBatis 的 Java 後端工程師。請根據需求編寫 Mapper 接口和 XML。

- MyBatis 版本與是否使用增強框架:[版本與框架](例:MyBatis 3.5,無 Plus)
- 數據庫:[數據庫](例:MySQL 8)
- 表結構:
  [粘貼建表語句]
- 需求:[查詢需求](例:訂單列表按多條件篩選並排序)
- 查詢條件(哪些可選、如何匹配):[查詢條件]
- 排序與分頁要求:[排序與分頁]

編寫要求:
1. 條件拼接使用 where、if、choose、trim、set 等標籤,保證任何條件組合下都不會出現多餘的 AND、OR 或逗號;所有條件都為空時的行為要明確(返回全部還是拒絕查詢,大表應避免無條件全表查詢)。
2. 防注入:值一律用 #{} 參數佔位;${} 只能用於無法參數化的部分(如排序字段、排序方向、表名),且必須在 Java 層用白名單校驗後再傳入,並在代碼中寫明。
3. 集合參數:IN 查詢用 foreach,集合為空時的處理(避免生成語法錯誤的空括號);集合很大時分批。
4. 模糊查詢:用數據庫的字符串拼接函數配合 #{},不要用 ${} 拼接百分號。
5. 批量插入與更新:給出 foreach 批量插入寫法,說明單條 SQL 長度與數據庫包大小限制,建議每批數量;對比執行器批處理方式的取捨。
6. 結果映射:字段與屬性的映射方式(駝峰自動映射或結果映射),一對多關聯查詢時避免 N+1 查詢。
7. 分頁:使用 limit 分頁或分頁插件時,說明深分頁的性能問題與替代方案。

輸出:Mapper 接口(帶參數註解)、XML、Java 層的白名單校驗代碼、一條典型條件組合下最終生成的 SQL(用於核對)。

高亮處換成你自己的內容:[版本與框架]、[數據庫]、[粘貼建表語句]、[查詢需求]、[查詢條件]、[排序與分頁]

ChatGPT Plus 充值

已被複製 0 次

使用說明

怎麼填變量:[查詢條件] 寫清每個條件是精確匹配、模糊匹配還是範圍,以及是否可選,例如「狀態可多選;下單時間為範圍,兩端都可選;商品名模糊匹配」。[排序與分頁] 中如果允許前端指定排序字段,AI 會生成白名單校驗。

常見坑:

  • 用 ${} 接收前端傳來的排序字段或模糊查詢關鍵字,是 MyBatis 項目中最常見的 SQL 注入來源。
  • 手寫 WHERE 1=1 再拼接 AND 雖然能用,但 where 標籤更乾淨;更要注意的是所有條件都為空時會變成全表查詢。
  • foreach 的集合為空時會生成 IN (),直接報語法錯誤。在 Java 層先判斷,或在 XML 中處理。

追問技巧:追問「把這個列表查詢改為游標分頁(基於上一頁最後一條的 ID)」,或「這個一對多的結果映射會產生幾次查詢,怎麼改成一次」。

示例輸出

示例,僅供參考(節選)
xml
<select id="search" resultType="com.example.order.OrderVO">
  SELECT id, order_no, status, amount, created_at
  FROM orders
  <where>
    <if test="userId != null"> AND user_id = #{userId} </if>
    <if test="statuses != null and statuses.size() > 0">
      AND status IN
      <foreach collection="statuses" item="s" open="(" separator="," close=")">#{s}</foreach>
    </if>
    <if test="keyword != null and keyword != ''">
      AND product_name LIKE CONCAT('%', #{keyword}, '%')
    </if>
    <if test="from != null"> AND created_at &gt;= #{from} </if>
  </where>
  ORDER BY ${sortColumn} ${sortDir}
  LIMIT #{limit}
</select>
java
private static final Map<String, String> SORT_COLUMNS = Map.of("time", "created_at", "amount", "amount");

String col = SORT_COLUMNS.getOrDefault(req.getSort(), "created_at");   // 白名單:只允許預設字段
String dir = "asc".equalsIgnoreCase(req.getDir()) ? "ASC" : "DESC";

同款作品

用這條提示詞做出來的作品;原作者會因此獲得積分

做同款

還沒有同款,來做第一個。

Nathaniel 的更多內容

同主題

同模型

0 條評論

登入 後參與評論

還沒有評論,來搶沙發~