mybatis学习之路----模糊查询实现

来源:互联网 发布:淘宝网怎么没有一淘了 编辑:程序博客网 时间:2024/06/05 17:04

点滴记载,点滴进步,愿自己更上一层楼。


废话不多说,进入主题。

项目还是在上篇  mybatis学习之路----非代理方式的增删改查用法 基础之上进行开发


一个简单的模糊查询sql。

SELECT * FROM t_user WHERE username LIKE '%黄%'
根据以上sql,查询结果。


像这样的用到模糊查询的地方很多。下面来介绍mybatis的三种方式。


1 使用${}代替#{}接收参数。此种方式有sql注入风险。关于sql注入在下面会有实例演示。

2 使用mysql的concat语法给传入参数拼%号。即concat('%',param,'%').

3 直接接收带%号的参数进行查询  此种方式存在硬编码,不推荐。


在user.xml中添加如下信息。也就是上面三种方法的实现

    <!--模糊查询 demo1 直接用${} 接收参数 此种方式有sql注入的危险    注意:如果parameterType为简单类型,最好写成${value}  写成别的很容易报错              There is no getter for property named 'username' in 'class java.lang.String',          如果parameterType为包装类型,和model中的属性对应即可-->    <select id="findUserByName1" parameterType="String" resultMap="userMap">        select * from t_user where username like '%${value}%'    </select>    <!--模糊查询 demo2 直接用concat拼字符串 此种可以有效防止sql注入 -->    <select id="findUserByName2" parameterType="String" resultMap="userMap">        select * from t_user where username like concat('%', #{username} ,'%')    </select>    <!--模糊查询 demo3 直接接收 拼好的参数  几接收参数就是 %参数% 形式,这种存在硬编码,不推荐 -->    <select id="findUserByName3" parameterType="String" resultMap="userMap">        select * from t_user where username like #{username}    </select>

UserDao.java中添加对应的接口

    /**     * 模糊查询第一种方式     * @param username 参数     * @return     */    List<User> findUserByName01(String username);    /**     * 模糊查询第二种方式  使用concat拼接查询命令     * @param username 参数     * @return     */    List<User> findUserByName02(String username);    /**     * 模糊查询第三种方式  直接接收拼好的字符串     * @param username 参数     * @return     */    List<User> findUserByName03(String username);

对应的实现    UserDaoImpl.java

        /**     * 模糊查询第一种方式     * @param username 参数     * @return     */    public List<User> findUserByName01(String username) {        String statementId = "test.findUserByName1";        return findUserList(statementId,username);    }    /**     * 模糊查询第二种方式  使用concat拼接查询命令     * @param username 参数     * @return     */    public List<User> findUserByName02(String username) {        String statementId = "test.findUserByName2";        return findUserList(statementId,username);    }    /**     * 模糊查询第三种方式  直接接收拼好的字符串     * @param username 参数     * @return     */    public List<User> findUserByName03(String username) {        String statementId = "test.findUserByName3";        return findUserList(statementId,username);    }    /**     * 由于都需要三种方式查询除了两个地方不一样其他的处理都相同,此处抽取相同部分     * @param statementId     * @param param     * @return     */    private List<User> findUserList(String statementId, Object param){        SqlSession sqlSession = null;        try {            sqlSession = SqlsessionUtil.getSqlSession();            return sqlSession.selectList(statementId,param);        } catch (Exception e) {            e.printStackTrace();        } finally {            SqlsessionUtil.closeSession(sqlSession);        }        return new ArrayList<User>();    }

基本实现已经完成,下面进行测试。

UserDaoTest.java  中添加对应的测试代码。

    @Test    public void findUserByName01() throws Exception {        List<User> users = dao.findUserByName01("黄");        for(User user:users){            System.out.println("findUserByName01:" + user);        }    }    @Test    public void findUserByName02() throws Exception {        List<User> users = dao.findUserByName02("黄");        for(User user:users){            System.out.println("findUserByName02:" + user);        }    }    @Test    public void findUserByName03() throws Exception {        // 此种方式存在硬编码,不推荐        List<User> users = dao.findUserByName03("%黄%");        for(User user:users){            System.out.println("findUserByName03:" + user);        }    }
三种方法测试结果。





到此,三种实现模糊查询方式示例完毕。


上面写到使用${}来接收参数的时候,说有sql注入的风险。那么什么是sql注入呢?

sql注入传送门

其实简单来说,传入的参数中有一段有风险的并且可执行sql代码。如果没有规避掉,可能是系统直接瘫痪。下面进行演示。


测试代码findUserByName01使用的是${}来接收参数,即

    @Test    public void findUserByName01() throws Exception {        List<User> users = dao.findUserByName01("黄");        for(User user:users){            System.out.println("findUserByName01:" + user);        }    }
这段代码怎么sql注入呢?

如果将参数修改成带有可执行sql的参数即("4' or username in (select username from t_user) or username like '3")
其中有了  or username in (select username from t_user)   这个条件,sql执行结果就是全表数据显示。

修改后带有sql注入的java代码。

    @Test    public void findUserByName01() throws Exception {        List<User> users = dao.findUserByName01("黄' or username in (select username from t_user) or username like '3");        for(User user:users){            System.out.println("findUserByName01:" + user);        }    }
执行结果。

可以看到全表的数据都显示出来了。

想想如果注入的sql是删除语句的话。。。。。。

但是同样的带有sql注入代码的参数,放到findUserByName02中,结果大不相同。

    @Test    public void findUserByName02() throws Exception {        List<User> users = dao.findUserByName02("黄' or username in (select username from t_user) or username like '3");        for(User user:users){            System.out.println("findUserByName02:" + user);        }    }

结果:


这就是说为什么,不提倡${}的方式来写模糊查询,而推荐使用concat拼接方式来进行模糊查询了。



原创粉丝点击