1.今天编写mybatis的xml语句发现需要把表名当做参数去完成sql。因此就不可避免的涉及#{}和${}亮仔传参方式,再次记录一下,让自己长个记性!
2.两者区别:
1.#{}为参数占位符?,即SQL预编译。${}为字符串替换,即SQL拼接,可以理解为仅仅是个纯碎的string替换,在动态SQL解析阶段将会进行变量替换。
2.#{}是“动态解析->预编译->执行”的过程。${}是“动态解析->编译->执行”的过程。
3.#{}的变量替换是在DBMS中。${}的变量替换是在DBMS外。
4.变量替换后,#{}对应的变量自动加上引号。变量替换后,${}对应的变量不会加上引号。
5. #{}能防止SQL注入。${}不能防止SQL注入
3.因此便得到以下使用场景:
(1) 能用#{}的地方就用#{},不用或少用${}。
(2) 表名作参数时,必须用${},例如select * from ${tableName}。
(3) ORDER BY时,必须用${},例如,select * from t_user order by ${columnName}
(4) 使用${}时,要注意何时加或不加单引号,即${}和'${}'。
(5) 存在隐式转换时,注意${}和#{}
4.开始碰到的表名作为参数问题也迎刃而解了!感谢各位大佬浏览!(注意要实现动态调用表名和字段名,就不能使用预编译了,需添加statementType="STATEMENT"")。
statementType:STATEMENT(非预编译),PREPARED(预编译)或CALLABLE中的任意一个,这就告诉 MyBatis 分别使用Statement,PreparedStatement或者CallableStatement。默认:PREPARED。这里显然不能使用预编译,要改成非预编译。
其次,sql里的变量取值是${xxx},不是#{xxx}。
因为${}是将传入的参数直接显示生成sql,如${xxx}传入的参数为字符串数据,需在参数传入前加上引号,如:
String tableName = "user";
tableName = "" + tableName + "";
5.切记传递参数需要使用map,不能使用字符串传参数。例如下面的查询,我需要传入参数 map.put("tableName","table_name"),如果传递参数为字符串是无法解析的;
<select id="qryTreeDataByTableName" parameterType="map" resultType="com.iwhalecloud.ids.desi.basedata.intentBill.dto.TreeDataDto" statementType="STATEMENT">
SELECT
distinct A.DATA_ID AS dataId ,
A.DATA_CODE AS 'key' ,
A.DATA_CODE AS 'value' ,
A.DATA_NAME AS 'title' ,
A.parent_id as parentId
from ${tableName} A
where A.STATE = '10A'
</select>