我们今天讲一个面试中经常会问的一个问题,就是#和$有什么作用,他们的区别是啥.
在MyBatis中提供了两种方式读取参数的内容到SQL语句中,分别是
#{参数名} :实体类对象或Map集合读取内容.
${参数名} :实体类对象或Map集合读取内容.
他们的区别是什么呢,还是看代码.
第一步:我们写的两个接口.
List selectJingHao(String name);
List selectMeiYuan(String name);
第二步:映射文件.
<select id="selectJingHao" resultMap="studentMap">
SELECT * from student where name=#{name}
</select>//记住美元符号where条件后的拼接字段要加引号
<select id="selectMeiYuan" resultMap="studentMap">
select * from student where name='${name}'
</select>
第三步:测试.
@Test
public void selectJingHao() throws Exception {
StudentMapper dao = session.getMapper(StudentMapper.class);
List<Student> student = dao.selectJingHao("jiepi");
student.stream().map(it -> it.toString()).forEach(System.out::println);
}
[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4516af24]
[DEBUG] ==> Preparing: SELECT * from student where name=?
[DEBUG] ==> Parameters: jiepi(String)
@Test
public void selectMeiYuan() throws Exception {
StudentMapper dao = session.getMapper(StudentMapper.class);
List<Student> student = dao.selectMeiYuan("jiepi");
student.stream().map(it -> it.toString()).forEach(System.out::println);
}
[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@530612ba]
[DEBUG] ==> Preparing: select * from student where name= 'jiepi'
[DEBUG] ==> Parameters:
String string
[DEBUG] <== Total: 1
使用 #{} 格式的语法会导致 MyBatis 创建 PreparedStatement 参数占位符并
安全地设置参数(就像使用 ? 一样)。这样做更安全,更迅速,通常也是首选做法,而使用${}格式语法,则就是字符串拼接,一般面试官问到这里就结束了,就怕有些自恋狂要问,那要${}有啥用.您不要慌,来看下面的代码.
第一步:接口
List selectTable(String table);
第二步 :映射文件
<select id="selectTable" resultMap="studentMap">
select * from ${value}
</select>
第三步:看结果
@Test
public void selectTable() throws Exception {
StudentMapper dao = session.getMapper(StudentMapper.class);
List<Student> student = dao.selectTable("student");
student.stream().map(it -> it.toString()).forEach(System.out::println);
}
[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2df32bf7]
[DEBUG] ==> Preparing: select * from student
[DEBUG] ==> Parameters:
可以看出有时你就是想直接在 SQL 语句中插入一个不转义的字符串.
当 SQL 语句中的元数据(如表名或列名)是动态生成的时候,字符串替换将会非常有用。举个例子,如果你想通过任何一列从表中 select 数据时,不要像下面这样写:
@Select("select * from user where id = #{id}")
User findById(@Param("id") long id);
@Select("select * from user where name = #{name}")
User findByName(@Param("name") String name);
@Select("select * from user where email = #{email}")
User findByEmail(@Param("email") String email);
可以只写这样一个方法:
@Select("select * from user where ${column} = #{value}")
User findByColumn(@Param("column") String column, @Param("value") String value);
其中 ${column} 会被直接替换,而 #{value} 会被使用 ? 预处理。因此你就可以像下面这样来达到上述功能:
User userOfId1 = userMapper.findByColumn("id", 1L);
User userOfNameKid = userMapper.findByColumn("name", "kid");
User userOfEmail = userMapper.findByColumn("email", "noone@nowhere.com");
官网:
用这种方式接受用户的输入,并将其用于语句中的参数是不安全的,会导致潜在的 SQL 注入攻击,因此要么不允许用户输入这些字段,要么自行转义并
检验.自然这也就是#和$的区别.
你都这样回答了面试官不录用你都难,欢迎持续关注.陆续介绍相关Mybatis知识点.