转自
https://blog.csdn.net/qq_15901351/article/details/82290032
项目开发过程中,在mybaitis框架中,sql经常需要动态赋值,会出现#{param} 、${param}两种形式。
接下来,我们一起来看一个案例:根据用户的姓名来筛选用户信息,其中用户姓名不确定,是动态变化的,sql如下:
select * from userInfo where user_name=“张三”; //查询名称是张三的信息
在xml中
select * from userInfo where user_name=#{name} //根据名称动态查询用户信息,#将参数解析成字符串
或者:
select * from userInfo where user_name=‘${name}' //$会将参数解析成对象 需要加上引号引住
一、主要区别如下:
1、#
将传入的参数都当成一个字符串
,会对自动传入的数据加一个双引号
。如:order by #{age}
,如果传入的值是18,那么解析成sql时的值为order by "18"
, 如果传入 age,则会解析为 order by "age"
2、 $
将传入的参数直接显示生成在sql中,被当成一个对象
。如:order by${age}
,如果传入的值是18,那么解析成sql时的值为order by 18
, 如果传入的值是age,则解析成的sql为 order by age
3、# 方式底层采用预编译方式PreparedStatement
,能够很大程度防止sql注入
;$方式底层只是Statement
,无法防止Sql注入
。
4、$ 方式一般用于传入数据库对象
,例如传入表名
。
5、一般能用#的就别用$
注意点:MyBatis排序时使用order by
动态参数时需要注意,用$而不是#
二、sql预编译
1、定义:
指数据库驱动在发送 sql 语句和参数
给 DBMS 之前对 sql 语句进行编译
,这样 DBMS 执行 sql 时,就不需要重新编译。
2、为什么需要预编译
JDBC 中使用对象 PreparedStatement 来抽象预编译语句
,使用预编译。预编译阶段可以优化 sql 的执行。预编译之后的 sql 多数情况下可以直接执行
,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。预编译语句对象可以重复利用
。把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来
,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象
。mybatis 默认
情况下,将对所有的 sql 进行预编译
。
三、案例:动态模糊查询
1、xml :
<!--商品关键字搜索 -->
<select id="searchKeyProductListByMap" parameterType="map"
resultType="com.test.index.model.ProductInfo">
select * from c_product_info
where state=1 and (product_name like '%${find_key}%'
or key_words_list like '%${find_key}%'
or product_brand like '%${find_key}%')
</select>
2、注解:
@Select({
"select",
"id, name, intro, learn_count, difficulty, score, image, publish_time, price, ",
"subject_id, direction_id, learn_time",
"from course where name like concat('%',#{name,jdbcType=VARCHAR},'%')"
})