mybatis中的#和$的区别:
1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id";
2. $将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id;
3. #方式能够很大程度防止sql注入;
4.$方式无法防止Sql注入;
5.$方式一般用于传入数据库对象,例如传入表名;
6.一般能用#的就别用$;
案例说明:
serverImpl文件:
public ModelResults expertQuery(JSONObject params){
//专家账号
String phone=params.getString("phone");
// 当前页
String page = params.getString("page");
// 每页显示数量
String pageSize = params.getString("pageSize");
if(ValidateUtil.isEmpty(page) || ValidateUtil.isEmpty(pageSize)){
page = Constants.PAGE_DEFUAL;
pageSize = Constants.PAGESIZE_DEFUAL;
}
ModelResults results = new ModelResults(Integer.valueOf(pageSize), Long.parseLong(page));
Map<String, Object> paramsMap = new HashMap<String, Object>();
paramsMap.put("phone", phone);
paramsMap.put("page", results.getStart());//传入的是字符串类型
paramsMap.put("pageSize",pageSize);//传入的是字符串类型
//查询专家
List<Map<String, Object>> expertList =expertDao.expertQuery(paramsMap);
//查询专家总数
long resultsCount = expertDao.countExpertQuery(phone);
if(ValidateUtil.isNotEmpty(expertList)){
<span style="white-space:pre"> </span>for(Map<String, Object> map:expertList){
//根据专家id查询专家擅长的车型
//专家id(Object不能直接转换Integer,Long需要toString()作为中间桥梁)
Long id=Long.valueOf(map.get("id").toString());
List<Map<String, Object>> expertGoodAtList=expertDao.findByExpertGoodAtId(id);
map.put("expertGoodAtList", expertGoodAtList);
}
}
results.setData(expertList);
results.setResultsCount(resultsCount);
results.setCode(MsgInfo.a_suc_code);
results.setMessage(MsgInfo.a_suc_msg);
return results;
}
dao文件:
List<Map<String, Object>> expertQuery(Map<String, Object> params);
则xml文件:
<select id="expertQuery" parameterType="java.util.Map" resultType="java.util.Map">
select id,phone,header_url AS
headerUrl,description,longitude,latitude,expert_name AS
expertName,expert_address AS expertAddress
from ykat_expert
where is_del=1
<if test="phone!=null and phone!='' ">
and phone=#{phone}
</if>
limit ${page} , ${pageSize}
</select>
由上面的案例可以看到,分页的参数page,pageSize传入的是string类型,在xml文件中使用的是$而不是#,若是用#,则自动对传入的数据加一个双引号,那么limit"page","pageSize",则sql语句会报错:
[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"0","10"' at line 5
若你封装的分页参数类型是数值类型则xml文件中既可以用$也可以用#
总结:
1.MyBatis排序时使用order by动态参数时需要注意用$而不是#(重点)
2.字符串替换,默认情况下,使用#{}格式的语法会导致MyBatis创建预处理语句属性并以它为背景设置安全的值(比如?)这样做很安全,很迅速也是首选做法,有时你只是想直接在SQL语句中插入一个不改变的字符串。比如,像ORDER BY,你可以这样来使用:ORDER BY ${columnName},这里MyBatis不会修改或转义字符串。(重点)
3.接受从用户输出的内容并提供给语句中不变的字符串这样做是不安全的,这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段或者通常自行转义并检查。
4.实际开发中会用的$有分页,排序,like模糊查询等。(重点)
5.实际开发中,若动态查询表名,列名,拼接的sql则必须用$,否则会解析异常。如:
<!-- 查询档案检索字段 -->
<select id="getEspData" parameterType="java.util.Map" resultType="java.util.Map">
select
${fields}
from ${tableName}
where ID = #{id}
</select>
这个案例很重要,日常开发中经常用