前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面试Mybatis之#和$

面试Mybatis之#和$

作者头像
小土豆Yuki
发布2020-06-15 17:38:18
3820
发布2020-06-15 17:38:18
举报
文章被收录于专栏:洁癖是一只狗

Mybatis之#和$

我们今天讲一个面试中经常会问的一个问题,就是#和$有什么作用,他们的区别是啥.

在MyBatis中提供了两种方式读取参数的内容到SQL语句中,分别是

#{参数名} :实体类对象或Map集合读取内容.

${参数名} :实体类对象或Map集合读取内容.

他们的区别是什么呢,还是看代码.

第一步:我们写的两个接口.

代码语言:javascript
复制
List selectJingHao(String name);
List selectMeiYuan(String name);

第二步:映射文件.

代码语言:javascript
复制
 <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>

第三步:测试.

代码语言:javascript
复制
   @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)
代码语言:javascript
复制
   @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 参数占位符并

安全地设置参数(就像使用 ? 一样)。这样做更安全,更迅速,通常也是首选做法,而使用${}格式语法,则就是字符串拼接,一般面试官问到这里就结束了,就怕有些自恋狂要问,那要${}有啥用.您不要慌,来看下面的代码.

第一步:接口

代码语言:javascript
复制
List selectTable(String table);

第二步 :映射文件

代码语言:javascript
复制
   <select id="selectTable" resultMap="studentMap">
        select *  from  ${value}
    </select>

第三步:看结果

代码语言:javascript
复制
    @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 数据时,不要像下面这样写:

代码语言:javascript
复制
@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); 

可以只写这样一个方法:

代码语言:javascript
复制
@Select("select * from user where ${column} = #{value}")
User findByColumn(@Param("column") String column, @Param("value") String value);

其中 ${column} 会被直接替换,而 #{value} 会被使用 ? 预处理。因此你就可以像下面这样来达到上述功能:

代码语言:javascript
复制
User userOfId1 = userMapper.findByColumn("id", 1L);
User userOfNameKid = userMapper.findByColumn("name", "kid");
User userOfEmail = userMapper.findByColumn("email", "noone@nowhere.com");

官网:

用这种方式接受用户的输入,并将其用于语句中的参数是不安全的,会导致潜在的 SQL 注入攻击,因此要么不允许用户输入这些字段,要么自行转义并

检验.自然这也就是#和$的区别.

你都这样回答了面试官不录用你都难,欢迎持续关注.陆续介绍相关Mybatis知识点.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 洁癖是一只狗 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Mybatis之#和$
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档