动态 sql 是 mybatis 的主要特性之一,在 mapper 中定义的参数传到 xml 中之后,在查询之前 mybatis 会对其进行动态解析。mybatis 提供了两种支持动态 sql 的语法:#{} 以及 ${} 。
1、#{} : 根据参数的类型进行合适的处理
比如传入String类型,会为参数加上双引号,如果传入Integer类型数据,则不会为参数加上双引号。#{} 传参在进行SQL预编译时,会把参数部分用一个占位符 ? 代替,这样可以防止 SQL注入。
2、${} : 将参数取出不做任何处理
直接放入语句中,就是简单的字符串替换,并且该参数会参加SQL的预编译,需要手动过滤参数防止 SQL注入。
3、因此 mybatis 中优先使用 #{}
当需要动态传入 表名或列名时,再考虑使用 ${} ,比较特殊,他的应用场景是需要动态传入表名或列名时使用,MyBatis排序时使用orderby动态参数时需要注意,用{} 比较特殊, 他的应用场景是 需要动态传入 表名或列名时使用,MyBatis排序时使用order by 动态参数时需要注意,用比较特殊,他的应用场景是需要动态传入表名或列名时使用,MyBatis排序时使用orderby动态参数时需要注意,用而不是 # 。
例如
1、#{} 对传入的参数视为字符串
mapper文件中的语句为
<select id="findUserByUserName" resultType="User" >
select * from user where userName = ${userName}
</insert>
例如传入的参数是 String userName = "root" ,mybatis处理后的则是
select * from user where userName = 'root'
2、#{} 对传入的参数视为数字类型
mapper文件中的语句为
<select id="findUserByUserId" resultType="User" >
select * from user where userId = ${userId}
</insert>
例如传入的参数是 int userId = 9527; ,mybatis处理后的则是
select * from user where userId = 9527
3、${} 不会将传入的值进行预编译
mapper文件中的语句为
<insert id="InsertColumnsInfo">
${insertSQL}
</insert>
例如传入的参数是一条SQl语句,
INSERT INTO columns_Info(tableName,columnName,columnType,columnLength,annotation) VALUE('z2','t2','VARCHAR',255,'annotation');
mybatis处理后不做任何改变,则是
INSERT INTO columns_Info(tableName,columnName,columnType,columnLength,annotation) VALUE('z2','t2','VARCHAR',255,'annotation');
总结
${} 可以在java代码中预先拼接复杂的SQL语句直接传入
#{} 优势在于它能很大程度防止sql注入,而${}不行
比如:用户进行一个登录操作,后台sql验证式样的:
<select id="userLogin" resultType="User" >
select * from user where user_name=#{name} and password = #{pwd}
</select>
如果前台传来的用户名是“rookie”,密码是 “1 or 2”,用 #{} 的方式就不会出现sql注入.
换成用 ${} 方式,sql语句就变成了
select * from user where user_name=rookie and password = 1 or 2
这样的话就形成了sql注入。