语法: /#{字符}
使用方式如下:
<select id="selectById" parameterType="integer" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where id=#{studentId}
</select>
mybatis处理/#{} 使用jdbc对象是 PrepareStatment对象:
// mybatis出创建PrepareStatement对象,执行sql语句
String sql=" select id,name,email,age from student where id=?";
PrepareStatement pst = conn.prepareStatement(sql);
pst.setInt(1,1001); //传递参数
ResultSet rs = pst.executeQuery(); //执行sql语句
语法 : ${字符}
<select id="selectById" parameterType="integer" resultType="com.bjpowernode.domain.Student">
select id,name,email,age from student where name=${studentName}
</select>
mybatis处理$ 占位符使用jdbc对象是 Statment对象,${} 表示字符串连接, 把sql语句的其他内容和 ${}内容使用 字符串(+) 连接的方式连在一起
String sql="select id,name,email,age from student where name=" + "lisi";
// mybatis创建Statement对象, 执行sql语句。
Statement stmt = conn.createStatement(sql);
ResultSet rs = stmt.executeQuery();
如果我们使用之前的传值方式:
Student students = mapper.selectByName("lisi");
可以看到lisi将原样拼接到SQL中,缺失引号,执行也会报错:
我们需要自行拼接引号才能使用:
Student students = mapper.selectByName("‘lisi’");
实现下面这个需求:
从不同的表中通过某个字段查询数据,并且通过某个字段排序。
接口、方法定义:
List<Student> selectStudentOrderByColumn(@Param("name") String name, @Param("column") String column,
@Param("tableName") String tableName);
mapper文件:
<!-- ${}常用作表名或列名 -->
<select id="selectStudentOrderByColumn" resultType="com.macay.entity.Student">
select id, name, email, age from ${tableName} where name = #{name} order by ${column}
</select>
测试类:
@Test
public void selectStudentOrderByColumn() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
List<Student> students = mapper.selectStudentOrderByColumn("macay","age","student");
students.forEach(student -> System.out.println(student));
sqlSession.close();
}
1、 /#使用的PrepareStatement对象,执行sql语句,效率高。能预编译,避免sql注入, sql语句执行更安全。$使用Statement对象,执行sql语句,效率低,相当于字符串拼接方式, 有sql注入的风险。 有代码安全的问题。
2、/#{} 常常作为 列值使用的, 位于等号的右侧,传入的数 据都当成一个字符串。而$常用作 表名或者列名。
3、/#{} 如果传递的参数是简单类型,里面的内容任意。$如果传递的是简单类型,里面的值必须是value。
比如说根据学生姓名查学生信息,会传入一个name的参数,假设学生姓名是方方,那么Sql就是:
SELECT id,name,age FROM student WHERE name = '方方';
在没有做防Sql注入的时候,我们的Sql语句可能是这么写的:
<select id="selectStudentByName" resultType="entity.Student">
SELECT id,name,age FROM student WHERE name = '${value}'
</select>
但如果我们对传入的姓名参数做一些更改,比如改成anything’ OR ‘x’='x,那么拼接而成的Sql就变成了:
SELECT id,name,age FROM student WHERE name = 'anything' OR 'x'='x'
库里面所有的学生信息都被拉了出来,是不是很可怕。原因就是传入的anything’ OR ‘x’='x和原有的单引号,正好组成了 ‘anything’ OR ‘x’='x’,而OR后面恒等于1,所以等于对这个库执行了查所有的操作。
防范Sql注入的话,就是要把整个anything’ OR ‘x’='x中的单引号作为参数的一部分,而不是和Sql中的单引号进行拼接.
使用了/#即可在Mybatis中对参数进行转义:
<select id="selectStudentByName" resultType="entity.Student">
SELECT id,name,age FROM student WHERE name = #{name}
</select>
我们看一下发送到数据库端的Sql语句长什么样子。
SELECT id,name,age FROM student WHERE name = 'anything\' OR \'x\'=\'x'
从上述代码中我们可以看到参数中的所有单引号统统被转义了,这都是JDBC中PrepareStatement的功劳,如果在数据库服务端开启了预编译,则是服务端来做了这件事情。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/weixin_44075963/article/details/116394630
内容来源于网络,如有侵权,请联系作者删除!