针对上一篇文章MyBatis 特殊字符转义拦截器 针对(_、\、%) , 经过自己简单的功能测试,发现所有请求参数为HashMap 的Select查询都进行了特性字符的过滤处理,会导致部分字典查询数据接口因为特殊字符的转换导致数据无法正常查询,进而影响系统的稳定性。
对于上述出现的问题,我这里提出的解决办法是:通过自定义TypeHandler类型处理器,来实现特俗字符的转义处理。
实现核心功能代码:
1、自定义TypeHandler
/*
* 针对String数据类型的转义器
*/
@MappedJdbcTypes(JdbcType.VARCHAR)
public class EscapeTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
throws SQLException {
parameter = EscapeUtil.repalceString(parameter);
ps.setString(i, parameter);
}
@Override
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
return super.getResult(rs, columnName);
}
@Override
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return super.getResult(rs, columnIndex);
}
@Override
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return super.getResult(cs, columnIndex);
}
}
2、 特殊字符转义工具类EscapeUtil
public class EscapeUtil{
private static final String ESCAPE_CHAR = "\";
/**
* 替换sql中的模糊特殊字符 _ %
*
* 该方法只在MyBatis + mysql下测试通过,如更换dao层框架或者数据库,则需重新测试
*
* 请注意,下面这种替换方式,只支持preparedstatement,即对应#{},而无法支持${}
*
* @param str 转义前的字符串
* @return 转义后的字符串
*/
public static String repalceString(String str) {
String result = null;
if (str != null) {
result = str.replace(ESCAPE_CHAR, ESCAPE_CHAR + ESCAPE_CHAR);
result = result.replace("%", ESCAPE_CHAR + "%");
result = result.replace("_", ESCAPE_CHAR + "_");
}
return result;
}
}
3、对需要转义的参数配置自定义TypeHandler
<if test="userName != null">
user_name like CONCAT(#{userName, typeHandler=com.zzg.handler.EscapeTypeHandler},'%')
</if>
针对MyBaties 特殊字符转义问题,我推荐使用自定义TypeHandler 方式。