首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

J2EE 自動構建 SQL 實戰:表單命名規約驅動 INSERT/UPDATE/DELETE 動態生成

     編輯:關於SqlServer

前言

Web 開發中大量重複的 CRUD SQL 手工編寫效率低、易出錯、維護難。本文提出一套基於**表單元素命名規約**的自動構建機制:約定前綴識別欄位類型 (字串/數值/函數)、公共參數 (表名/操作類型/WHERE 條件),配合 JavaBean 反射 `request.getParameterNames()` 動態生成標準 SQL,實現「改表單即改邏輯」的極致解耦。

一、 命名規約設計

前綴語義SQL 處理範例
c_公共參數直接提取值c_table=users, c_genre=INSERT/UPDATE/DELETE, c_where=id=1
s_字串型欄位單引號包裹 + 單引號轉義 (' → '')s_username=admin → 'admin'
i_數值/函數型欄位直接拼接 (無引號)i_age=25, i_created=now()

二、 核心 JavaBean 實現

package com.river.page;
import java.util.*;
import javax.servlet.http.HttpServletRequest;

public class PageUtil {
    private HttpServletRequest request;
    public void init(HttpServletRequest req) { this.request = req; }
    public void clear() { this.request = null; }
    public String get(String name) { return (request!=null && request.getParameter(name)!=null) ? request.getParameter(name) : ""; }

    public String getSQL() {
        String c_table = get("c_table"), c_genre = get("c_genre"), c_where = get("c_where");
        if (c_genre==null || c_genre.isEmpty()) return "action empty";
        if (c_table==null || c_table.isEmpty()) return "table empty";

        Enumeration names = request.getParameterNames();
        StringBuilder cols = new StringBuilder(), vals = new StringBuilder(), sets = new StringBuilder();

        while (names.hasMoreElements()) {
            String name = names.nextElement().trim();
            if (name.length() < 2) continue;
            String prefix = name.substring(0,2), col = name.substring(2), val = get(name);

            if (prefix.equalsIgnoreCase("i_")) {
                if (c_genre.equalsIgnoreCase("INSERT")) {
                    cols.append(",").append(col);
                    vals.append(",").append(val.isEmpty() ? "NULL" : val);
                } else if (c_genre.equalsIgnoreCase("UPDATE")) {
                    sets.append(",").append(col).append("=").append(val.isEmpty() ? "NULL" : val);
                }
            } else if (prefix.equalsIgnoreCase("s_")) {
                if (c_genre.equalsIgnoreCase("INSERT")) {
                    cols.append(",").append(col);
                    vals.append(",").append(val.isEmpty() ? "NULL" : "'"+val.replaceAll("'","''")+"'");
                } else if (c_genre.equalsIgnoreCase("UPDATE")) {
                    sets.append(",").append(col).append("=").append(val.isEmpty() ? "NULL" : "'"+val.replaceAll("'","''")+"'");
                }
            }
        }

        String sql;
        if (c_genre.equalsIgnoreCase("INSERT")) {
            if (cols.length()>0) { cols.deleteCharAt(0); vals.deleteCharAt(0); }
            sql = "INSERT INTO "+c_table+" ("+cols+") VALUES ("+vals+")";
        } else if (c_genre.equalsIgnoreCase("UPDATE")) {
            if (sets.length()>0) sets.deleteCharAt(0);
            sql = "UPDATE "+c_table+" SET "+sets + (c_where!=null && !c_where.isEmpty() ? " WHERE "+c_where : "");
        } else if (c_genre.equalsIgnoreCase("DELETE")) {
            sql = "DELETE FROM "+c_table + (c_where!=null && !c_where.isEmpty() ? " WHERE "+c_where : "");
        } else {
            return "unknown action: "+c_genre;
        }
        return sql;
    }
}

三、 使用範例

表單輸入:

  • `c_table=users`, `c_genre=INSERT`, `c_where=`
  • `s_username=admin`, `s_email=test@test.com`, `i_age=25`, `i_created=now()`

生成 SQL:

INSERT INTO users (username,email,age,created) VALUES ('admin','test@test.com',25,now())

四、 優缺點權衡

優點缺點
極大減少樣板代碼,欄位增減只改表單反射遍歷參數有效能開銷 (大表單明顯)
統一處理單引號轉義、NULL、函數直寫動態 SQL 難以靜態分析/優化 (計畫快取碎片化)
表單與邏輯解耦,結構變更零代碼修改安全性依賴命名規約執行,惡意參數可能構造非預期 SQL
易擴展:加入自動執行類 → 通用 CRUD Action不適用複雜邏輯 (多表聯結、子查詢、事務控制)

五、 進階擴展建議

  • 整合 `PreparedStatement` 參數化綁定 (而非字串拼接) → 防注入 + 計畫複用。
  • 加入欄位驗證註解 (長度、格式、必填) → 表單端同步生成 JS 驗證。
  • 支援批次操作 (陣列參數 `s_tags[]`) → 生成多值 INSERT / IN 列表。
  • 引入快取機制 (按 `c_table`+`c_genre`+`欄位集合` 快取 SQL 模板)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved