iBATIS update 特殊字元處理
阿新 • • 發佈:2018-12-31
在近期專案中發現有部分使用者投訴檔名中帶有 單引號、反斜槓及雙引號(‘ 、 “)的檔案無法上傳或者檔名中少了反斜槓或雙引號,經查實後發現後臺執行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格式返回的服務,需要對< > & 等字元做進一步處理。