mybatis中的#号和$号的区别

时间:2021-05-02 04:00:31

之前做项目时,由于自己对之前学过的,用过的知识都没有去总结,时间一久,就会忘记,而当出现问题时,往往需要很长时间才能找到问题原因,从而浪费了大量时间在定位上,言归正传,现在说说之前遇到的一个问题。

使用mybatis时动态传参,我们都知道使用#{},这也是绝大多数场景用到的,

而有一次,我需要在后台拼接查询参数,放入in中,我拼接的参数格式为‘p001','p002','p003'这样的,in条件的写法in (#{product})

结果就是查询不到数据,但是把sql和参数拿到plsql中却完全没问题,当时脑子短路,一直没想到问题的原因在哪,白白牺牲了将近一下午时间。

后来突然想到$符号,后来将$符号代替#号就OK了。


问题原因:

#{} 默认会用引号将参数引起来

${} 单纯替代。

之前的写法,select * from product_tree_v pv where pv.product_code in(#{product})

预编译出来的结果:select * from product_tree_v pv where pv.product_code in ?;

#{}被当作一个占位符了,而参数前后也会被加上引号。

运行时的sql是:select * from product_tree_v pv where pv.product_code in('‘p001','p002','p003'');

所以无论如何都是查不到数据的。

换成${}:select * from product_tree_v pv where pv.product_code in($product});

预编译出来的结果 :select * from product_tree_v pv where pv.product_code in (‘p001','p002','p003');

这样就是纯粹的将参数传进去,没有做任何的转义操作。这才是我们真正想要的。


总结:

mybatis作为ORM框架,从性能,系统维护性,实用性上来说,都是非常优秀的,

其所有的sql在执行前都会通过数据库驱动进行预编译,这样DBMS就可以不用编译直接接收参数运行,

而#和$号的区别在预编译后就能看出来了,#{}预编译完是占位符?,而${}预编译完就是传进来的参数。


#{}的优点:

  使用#{}可以预防sql攻击,而${}却不能

例如 select * from ${tablename}   如果传入的是 product; drop product;

那么你的表数据就会被无声无息的干掉了。

使用${}的场景:

1 作为in条件时,

        2 参数为int类型并且数据库中字段的类型是number,

        3 表名

        4 order by ${},排序字段


--------ps---------

<![CDATA[]]>的用法,在该符号内的语句,将不会被当成字符串来处理,而是直接当成sql语句,比如有大于,小于号,要执行一个存储过程

都需要加上这个。