1. 程式人生 > >iBATIS update 特殊字元處理

iBATIS update 特殊字元處理

在近期專案中發現有部分使用者投訴檔名中帶有  單引號、反斜槓及雙引號(‘ 、 “)的檔案無法上傳或者檔名中少了反斜槓或雙引號,經查實後發現後臺執行SQL異常:

org.springframework.jdbc.BadSqlGrammarException: SqlMapClient operation; bad SQL grammar []; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred while applying a parameter map.  
--- Check the com.cn21.edrive.mysql.persistence.file.dao.model.FMUploadFilePart.updateByPrimaryKeySelective-InlineParameterMap.  
--- Check the statement (update failed).  
--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: com.foundationdb.sql.parser.SQLParserException: Encountered " <EXACT_NUMERIC> "1. "" at line 1, column 140.
Was expecting one of:
    <EOF> 
    "and" ...
    "collate" ...
    "is" ...
    "where" ...
    "returning" ...
    "," ...
    
    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:233)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:203)
    at org.springframework.orm.ibatis.SqlMapClientTemplate.update(SqlMapClientTemplate.java:378)

 

從日誌上看,sql語法出錯,可能出現關鍵字衝突。debug匯出相關的sql檢視:
update fm_upload_file_part   set   OPER_ID = ?  ,  FILE_OWNER_ID =   ? ,     FILE_NAME =   ?         where UPLOAD_FILE_ID = ?  

引數值 2'1.jpg 帶有上引號,導致sql語法錯誤
 Parameters: [8546, 8546, 2'1.jpg, 31468211402]

該sql是由iBATIS生成,檢視sql_map.xml, 欄位fileName使用的是#變數傳參的形式,所以將2'1.jpg賦值給sql語句造成語法錯誤。後來改成 "$fileName$" 字串直接替換的形式解決了sql語法問題。


 <isNotNull prepend="," property="fileName">
       FILE_NAME = "$fileName$"
       <!-- #fileName:VARCHAR# --> 
 </isNotNull>

在解決了sql語法問題之後,需要在上層業務層對fileName做特殊字元轉義,通常採用新增反斜槓的形式進行轉義:
public static String encodingFileName4MysqlQuota(String fileName) {
        String result = fileName;
        if (fileName != null && fileName.length() > 0) {
            try {

                result = result .replaceAll("\\\\", "\\\\\\\\");//反斜槓 \  轉義
                result = fileName.replaceAll("'", "\\\\'");//單引號 ' 轉義
                result = result .replaceAll("\"", "\\\\\"");// 雙引號 “ 轉義
                //過濾不允許的特殊字元
                if (result != null && result.length() > 0  ) {
                    result = result.replaceAll("[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]", "");
                }
                log.debug("encodingFileName4MysqlQuota() - result=" + result );
                
            } catch (Exception e) {
                log.warn("encodingFileName4MysqlQuota() - fileName=" + fileName, e);
                result = fileName;
            }
         
        }
        return result;
    }

至於反斜槓的數目,主要是考慮了java 轉義->正則表示式轉義->mysql轉義等幾層,如剝洋蔥般層層轉義。有時平臺側和資料庫連線時經過了MyCat等中介軟體,肯能還需要進一步轉義,視具體情況而定,做好相應的單元測試,檢查寫入是否正確。

單元測試後 名為 1'2ww"ee"<> & % #$*.jpg 的圖片可成功入庫。

對於需要將該資料讀取後以xml格式返回的服務,需要對< > & 等字元做進一步處理。