由于没分清mybatis中的$和#的区别,在处理数据上折腾了许久。
案例如下:
我要通过在实体MisWorkflowCommon中取值,在mybatis对应的映射文件的SQL中获取到对应的值,从而进行update处理,修改后的部分mybatis文件如下:
<update id="updateServiceStatus" parameterType="com.jiayou.cps.pojo.workflowCommon.MisWorkflowCommon"> update ${tableName} set ${statusColumn} = ${statusVal} where id = ${serviceId} and del_flag = ‘0‘ </update>
上述值如果不用$,而是用#的话,那么控制台打印的SQL日志为update ? set ? = ? ...的形式,并没有读出对应的数据映射到SQL的字段中。
有些人会在update标签中加statementType="STATEMENT"参数,此处是不需要添加的,因为使用$就已经是非预编译的了。
statusColumn是字符串类型,在java对应的controller中对数据进行拼串处理,部分代码如下:
MisWorkflowCommon model = list.get(0); model.setStatusVal("‘"+statusVal+"‘"); model.setServiceId(Integer.valueOf(serviceId.substring(3, serviceId.length()))); int updateNum = this.misWorkflowCommonService.updateServiceStatus(model);
此处要注意$和#的区别:
$部分
$直接显示当前值,不会做其他处理,所以在做动态传值的时候要用$,比如我遇见的上述情况,当然,当你要用字段进行排序,也是需要使用$的。
$运行非预编译sql 会导致sql硬解析,如果这个语句执行的比较频繁,会导致数据库性能下降。
$无法防止SQL注入,这种方式类似于用Statement处理SQL。
#部分
#当成字符串处理,在值的两边会加上双引号"‘",比如select * from table where name=#{column},那么最终结果是select * from table where name=‘test‘。
#能在很大程序上防止SQL注入,这种方式类似于用Preparedstatement处理SQL,会产生对应的占位符,因为sql语句已经预编译好了,传入参数的时候,不会重新生产sql语句,安全性高,所以能用#就别用$。
参照网站:
http://www.mybatis.org/mybatis-3/sqlmap-xml.html#String_Substitution
http://www.cnblogs.com/kangyun/p/5881531.html