mybatis中的$与#的区别以及模糊查询

首先我们要知道mybatis中使用jdbc连接数据库的时候使用的是preparedStatement还是statement?
这里说明一下,如果我们在mapper文件中的sql语句中写的是$进行参数传递那么它就会拼接成字符串,然会执行,实际上使用的就是statement,但是如果我们用#进行参数传递,他使用的就是preparedStatement,可以防止sql注入。
那么我们不就全都用#不就行了吗?
下面我们就研究一下他们俩的区别,也就是能用$而不能使用#的地方。

在mybatis中,”${xxx}”这样格式的参数会直接参与sql编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${xxx}”这样的参数格式,所以,这样的参数需要我们在代码中手工进行处理来防止注入。

实验:
在这里插入图片描述
使用预编译的数据库操作对象进行注入值的时候,列名是不能够被写入的。你看上面我们让它降序排列但是并没有。
在这里插入图片描述
所以在mybatis中的$符号可以直接替换掉列明,这就是能够用$二不能用#的地方。

那么这种情况下如何避免sql注入呢?
实验:
我们数据库中的数据:
在这里插入图片描述

<select id="getAllUserLike" resultType="com.dongmu.pojo.User">
        select * from User where name like  "%"#{param}
    </select>

测试代码:

 @org.junit.Test
    public void test04(){
        SqlSession session = MybatisUtil.getSession();
        UserDao mapper = session.getMapper(UserDao.class);
        List<User> users = new ArrayList<>();
        users=mapper.getAllUserLike("i");
        session.close();
        for (User user : users) {
            System.out.println(user);
        }
    }

查询结果

User{id=1, name='lisi', pwd='123'}
User{id=7, name='husi', pwd='222'}
User{id=8, name='kiki', pwd='000'}

因为有的场合必须用$,我们把%改成$

<select id="getAllUserLike" resultType="com.dongmu.pojo.User">
        select * from User where name like  '%${param}'
    </select>

在这里插入图片描述
在这里插入图片描述
附上代码:

@org.junit.Test
    public void test04(){
        SqlSession session = MybatisUtil.getSession();
        UserDao mapper = session.getMapper(UserDao.class);

        List<User> users = new ArrayList<>();
        users=mapper.getAllUserLike("i' or '1'='1");
//        users=mapper.getAllUserLike("i");

        session.close();

        for (User user : users) {
            System.out.println(user);
        }



    }

看到sql注入了吧,所以在编写mybatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。


版权声明:本文为qq_45401910原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。