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格式返回的服务,需要对< > & 等字符做进一步处理。













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值