#{}与${}的区别和使用选择

在我们开始使用mapper配置文件来进行编写SQL语句的时候,我们一直使用#{}来进行传参,我们传入一个对象,通过自动获取对象的属性来进行与SQL语句进行交互,其实在传参的时候,还有一种方式,就是:${},那么我们来说一下他们的区别。


#{}与${}的区别和使用选择

#{}:               会把参数的位置使用”?”做占位符,执行SQL的时候才会替换”?”的值 

我们在使用Mybatis时,里面封装的进行与数据库进行交互的方法默认的是使用PrepareStatement,进行预编译,然后再把参数通过占位符?来执行SQL语句,而这种情况大多是对于insert,update的插入和修改值以及where后面进行判断的条件的参数,而这些内容都会有一个特点,是对数据库中的数据进行交互,大部分时间是需要加上一对单引号来进行区分其他语句中的关键词。

我们来执行一个插入语句:

#{}在把参数放入占位符的时候,会自动的给外层加上一对单引号。

然后我们把同样的语句放入数据库中再次执行一次:

我们知道里面的age,salary等属性是不用加单引号的,但是加了单引号也不会报错,也会正常的进行插入。

${}:                   直接把参数中的值作为SQL的一部分来执行

   我们进行插入代码的修改    把#换成$:

        <insert id="insertEmp" useGeneratedKeys="true" keyColumn="e_id" keyProperty="id">
            insert into emp (e_name,e_age,e_birthday,e_salary) values (${name},${age},${birthday},${salary})
        </insert>

再次进行测试:

如果把这句话放入数据库是什么情况呢?

我们会发现,这里面的字符串属性已经和数据库对不上了,如果不加单引号,那么就会报错。

那么我们又想到了SQL语句注入问题,我们模拟一个登陆操作。

        <select id="findEmpByNameAndAge3" resultMap="useResultMap">
            select e_id,e_name,e_age,e_birthday,e_salary from emp where e_name = #{name} and e_age = #{age}
        </select>

我们可以看到因为年龄参数不对应,所以没有查到,也就相当于无法登陆。

但是我们如果把查询语句中的#改为$

        <select id="findEmpByNameAndAge3" resultMap="useResultMap">
            select e_id,e_name,e_age,e_birthday,e_salary from emp where e_name = ${name} and e_age = #{age}
        </select>

测试语句改为:

    @Test
    public void testfindEmpByNameAndAge3() {
        EmpService service = new EmpServiceImpl();
        Emp emp = service.findEmpByNameAndAge3("'佐助' or '1' = '1'",100099);
        System.out.println(emp);
    }

再次测试:

成功了,所以用了$,还是会有注入问题。

那么${}有什么作用呢?

我们进行一个排序查询操作:

//根据年龄字段进行排序输出

//mapper接口方法

List<Emp> findAllEmpOrder(@Param("column") String column);

//查询语句
        <select id="findAllEmpOrder" parameterType="string" resultMap="useResultMap" >
            select e_id,e_name,e_age,e_birthday,e_salary from emp order by #{column} desc
        </select>

//service实现类方法
    @Override
    public List<Emp> findAllEmpOrder(String column) {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> list = mapper.findAllEmpOrder(column);
        return list;
    }

//测试方法
    @Test
    public void testfindAllEmpOrder(){
        EmpService service = new EmpServiceImpl();
        List<Emp> list = service.findAllEmpOrder("e_age");
        for(Emp emp : list){
            System.out.println(emp);
        }
    }

结果:

并没有进行年龄排序。

我们再把#换成$其他方法不变,再次进行查询

因为在SQL查询语句中是需要:

select e_id,e_name,e_age,e_birthday,e_salary from emp order by e_age desc

在order by 字段后面的内容是不需要用单引号引起来的。

这也是${}的一个作用。


区别

我们发现非常重大的区别,就是传入的信息是否用单引号引起来还能够发挥作用。

还能够的就使用#{}    ,不能够的就使用${}

这也就是两者用来判断使用哪个的重要条件和最快捷的实验的方式

 

 

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值