MyBatis-15MyBatis动态SQL之【bind】

简介: MyBatis-15MyBatis动态SQL之【bind】

概述

bind标签可以使用OGNL表达式创建一个变量并将其绑定到上下文中。


用法

我们用之前的一个例子作为讲解

<select id="selectSysUsersAdvancedWithWhere" resultType="com.artisan.mybatis.xml.domain.SysUser">
        SELECT
            a.id,
            a.user_name userName,
            a.user_password userPassword,
            a.user_email userEmail,
            a.user_info userInfo,
            a.head_img headImg,
            a.create_time createTime
        FROM
            sys_user a
        <where>
            <if test="userName != null and userName != '' ">
                and user_name like concat('%',#{userName},'%')
            </if>
            <if test="userEmail != null and userEmail != '' ">
                and user_email = #{userEmail}
            </if>
        </where>
    </select>


使用concat函数连接字符串,在MySQL中,这个函数支持多个参数,但是在Oracle中只支持两个参数。 由于不同数据库之间的语法差异,如果更换了数据库,有些SQL语句可能就需要重写。 针对这种情况,可以使用bind标签来避免由于更换数据库带来的一些麻烦。 我们将上面的语句改为bind方式,如下

<select id="selectSysUserByAdvancedCondition" resultType="com.artisan.mybatis.xml.domain.SysUser">
        SELECT
            a.id,
            a.user_name userName,
            a.user_password userPassword,
            a.user_email userEmail,
            a.user_info userInfo,
            a.head_img headImg,
            a.create_time createTime
        FROM
            sys_user a
        <where>
            <if test="userName != null and userName != '' ">
                <!-- and user_name like concat('%',#{userName},'%') -->
                <bind name="userNameLike" value=" '%' + userName + '%' "/>
                    and user_name like #{userNameLike}
            </if>
            <if test="userEmail != null and userEmail != '' ">
                and user_email = #{userEmail}
            </if>
        </where>
    </select>   


bind标签的两个属性都是不选项,name为绑定到上下文的变量名,value为OGNL表达式,创建一个bind标签后,就可以在下面直接使用了。 使用bind拼接字符串不仅可以避免因更换数据库而修改SQL,也能预防SQL注入。


示例

1.增加接口方法

/**
     * 
     * 
     * @Title: selectSysUserByAdvancedCondition
     * 
     * @Description: 演示bind用法
     * 
     * @param sysUser
     * @return
     * 
     * @return: List<SysUser>
     */
    List<SysUser> selectSysUserByAdvancedCondition(SysUser sysUser);


2.配置动态SQL

<select id="selectSysUserByAdvancedCondition" resultType="com.artisan.mybatis.xml.domain.SysUser">
        SELECT
            a.id,
            a.user_name userName,
            a.user_password userPassword,
            a.user_email userEmail,
            a.user_info userInfo,
            a.head_img headImg,
            a.create_time createTime
        FROM
            sys_user a
        <where>
            <if test="userName != null and userName != '' ">
                <!-- and user_name like concat('%',#{userName},'%') -->
                <bind name="userNameLike" value=" '%' + userName + '%' "/>
                    and user_name like #{userNameLike}
            </if>
            <if test="userEmail != null and userEmail != '' ">
                and user_email = #{userEmail}
            </if>
        </where>
    </select>   


3.单元测试

@Test
    public void selectSysUserByAdvancedConditionTest() {
        logger.info("selectSysUserByAdvancedConditionTest");
        // 获取SqlSession
        SqlSession sqlSession = getSqlSession();
        List<SysUser> userList = null;
        try {
            // 获取UserMapper接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            logger.info("===========1.当用户只输入用户名时,需要根据用户名模糊查询===========");
            // 模拟前台传参 1.当用户只输入用户名时,需要根据用户名模糊查询
            SysUser sysUser = new SysUser();
            sysUser.setUserName("ad");
            // 调用selectSysUserByAdvancedCondition,根据查询条件查询用户
            userList = userMapper.selectSysUserByAdvancedCondition(sysUser);
            // 根据数据库sys_user表中的记录,可以匹配到admin, 期望userList不为空
            Assert.assertNotNull(userList);
            // 根据查询条件,期望只有1条数据
            Assert.assertTrue(userList.size() == 1);
            logger.info("userList:" + userList);
            // 为了测试 匹配多条记录的情况,我们将id=1001这条数据的userName 由test 改为artisan
            sysUser.setUserName("i");
            // 调用selectSysUserByAdvancedCondition,根据查询条件查询用户
            userList = userMapper.selectSysUserByAdvancedCondition(sysUser);
            // 根据数据库sys_user表中的记录,可以匹配到admin和artisan, 期望userList不为空
            Assert.assertNotNull(userList);
            // 根据查询条件,期望只有2条数据
            Assert.assertTrue(userList.size() == 2);
            logger.info("userList:" + userList);
            logger.info("===========2.当用户只输入邮箱使,根据邮箱进行完全匹配===========");
            // 模拟前台传参 2.当用户只输入邮箱使,根据邮箱进行完全匹配
            sysUser.setUserEmail("admin@artisan.com");
            userList = userMapper.selectSysUsersAdvanced(sysUser);
            Assert.assertNotNull(userList);
            Assert.assertTrue(userList.size() == 1);
            logger.info(userList);
            sysUser.setUserEmail("1admin@artisan.com");
            userList = userMapper.selectSysUserByAdvancedCondition(sysUser);
            Assert.assertTrue(userList.size() == 0);
            logger.info("===========3.当用户同时输入用户名和密码时,用这两个条件查询匹配的用户===========");
            // 模拟组合查询条件,存在记录的情况
            sysUser.setUserName("i");
            sysUser.setUserEmail("admin@artisan.com");
            userList = userMapper.selectSysUserByAdvancedCondition(sysUser);
            Assert.assertNotNull(userList);
            Assert.assertEquals("admin@artisan.com", sysUser.getUserEmail());
            Assert.assertTrue(userList.size() == 1);
            logger.info(userList);
            logger.info("===========4.当用户同时输入无法匹配的用户名和密码===========");
            // 模拟组合查询条件,不存在记录的情况
            sysUser.setUserName("x");
            sysUser.setUserEmail("admin@artisan.com");
            userList = userMapper.selectSysUserByAdvancedCondition(sysUser);
            Assert.assertTrue(userList.size() == 0);
            logger.info(userList);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
            logger.info("sqlSession close successfully ");
        }
    }


日志

2018-04-24 20:57:44,130  INFO [main] (BaseMapperTest.java:26) - sessionFactory bulit successfully
2018-04-24 20:57:44,133  INFO [main] (BaseMapperTest.java:29) - reader close successfully
2018-04-24 20:57:44,137  INFO [main] (UserMapperTest.java:861) - selectSysUserByAdvancedConditionTest
2018-04-24 20:57:44,155  INFO [main] (UserMapperTest.java:870) - ===========1.当用户只输入用户名时,需要根据用户名模糊查询===========
2018-04-24 20:57:44,840 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like ? 
2018-04-24 20:57:44,931 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: %ad%(String)
2018-04-24 20:57:44,983 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-24 20:57:44,985 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-24 20:57:44,995 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
2018-04-24 20:57:45,001  INFO [main] (UserMapperTest.java:880) - userList:[SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-24 20:57:45,002 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like ? 
2018-04-24 20:57:45,004 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: %i%(String)
2018-04-24 20:57:45,006 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-24 20:57:45,006 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-24 20:57:45,008 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1001, artisan, 123456, test@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-24 20:57:45,010 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 2
2018-04-24 20:57:45,012  INFO [main] (UserMapperTest.java:891) - userList:[SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018], SysUser [id=1001, userName=artisan, userPassword=123456, userEmail=test@artisan.com, userInfo=测试用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-24 20:57:45,012  INFO [main] (UserMapperTest.java:893) - ===========2.当用户只输入邮箱使,根据邮箱进行完全匹配===========
2018-04-24 20:57:45,013 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE 1=1 and user_name like concat('%',?,'%') and user_email = ? 
2018-04-24 20:57:45,014 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: i(String), admin@artisan.com(String)
2018-04-24 20:57:45,016 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-24 20:57:45,016 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-24 20:57:45,017 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
2018-04-24 20:57:45,018  INFO [main] (UserMapperTest.java:899) - [SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-24 20:57:45,018 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like ? and user_email = ? 
2018-04-24 20:57:45,019 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: %i%(String), 1admin@artisan.com(String)
2018-04-24 20:57:45,020 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 0
2018-04-24 20:57:45,021  INFO [main] (UserMapperTest.java:905) - ===========3.当用户同时输入用户名和密码时,用这两个条件查询匹配的用户===========
2018-04-24 20:57:45,022 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like ? and user_email = ? 
2018-04-24 20:57:45,023 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: %i%(String), admin@artisan.com(String)
2018-04-24 20:57:45,024 TRACE [main] (BaseJdbcLogger.java:151) - <==    Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime
2018-04-24 20:57:45,024 TRACE [main] (BaseJdbcLogger.java:151) - <==        Row: 1, admin, 123456, admin@artisan.com, <<BLOB>>, <<BLOB>>, 2018-04-13 21:12:47.0
2018-04-24 20:57:45,025 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 1
2018-04-24 20:57:45,026  INFO [main] (UserMapperTest.java:914) - [SysUser [id=1, userName=admin, userPassword=123456, userEmail=admin@artisan.com, userInfo=管理员用户, headImg=[18, 49, 35, 18, 48], createTime=Fri Apr 13 21:12:47 BOT 2018]]
2018-04-24 20:57:45,026  INFO [main] (UserMapperTest.java:916) - ===========4.当用户同时输入无法匹配的用户名和密码===========
2018-04-24 20:57:45,027 DEBUG [main] (BaseJdbcLogger.java:145) - ==>  Preparing: SELECT a.id, a.user_name userName, a.user_password userPassword, a.user_email userEmail, a.user_info userInfo, a.head_img headImg, a.create_time createTime FROM sys_user a WHERE user_name like ? and user_email = ? 
2018-04-24 20:57:45,028 DEBUG [main] (BaseJdbcLogger.java:145) - ==> Parameters: %x%(String), admin@artisan.com(String)
2018-04-24 20:57:45,029 DEBUG [main] (BaseJdbcLogger.java:145) - <==      Total: 0
2018-04-24 20:57:45,029  INFO [main] (UserMapperTest.java:922) - []
2018-04-24 20:57:45,031  INFO [main] (UserMapperTest.java:928) - sqlSession close successfully 


相关文章
|
6月前
|
SQL Java 数据库连接
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
【YashanDB知识库】解决mybatis的mapper文件sql语句结尾加分号";"报错
|
5月前
|
SQL Java 数据库连接
MyBatis动态SQL字符串空值判断,这个细节99%的程序员都踩过坑!
本文深入探讨了MyBatis动态SQL中字符串参数判空的常见问题。通过具体案例分析,对比了`name != null and name != &#39;&#39;`与`name != null and name != &#39; &#39;`两种写法的差异,指出后者可能引发逻辑混乱。为避免此类问题,建议在后端对参数进行预处理(如trim去空格),简化MyBatis判断逻辑,提升代码健壮性与可维护性。细节决定成败,严谨处理参数判空是写出高质量代码的关键。
608 0
|
4月前
|
SQL XML Java
菜鸟之路Day35一一Mybatis之XML映射与动态SQL
本文介绍了MyBatis框架中XML映射与动态SQL的使用方法,作者通过实例详细解析了XML映射文件的配置规范,包括namespace、id和resultType的设置。文章还对比了注解与XML映射的优缺点,强调复杂SQL更适合XML方式。在动态SQL部分,重点讲解了`&lt;if&gt;`、`&lt;where&gt;`、`&lt;set&gt;`、`&lt;foreach&gt;`等标签的应用场景,如条件查询、动态更新和批量删除,并通过代码示例展示了其灵活性与实用性。最后,通过`&lt;sql&gt;`和`&lt;include&gt;`实现代码复用,优化维护效率。
289 5
|
SQL Java 测试技术
3、Mybatis-Plus 自定义sql语句
这篇文章介绍了如何在Mybatis-Plus框架中使用自定义SQL语句进行数据库操作。内容包括文档结构、编写mapper文件、mapper.xml文件的解释说明、在mapper接口中定义方法、在mapper.xml文件中实现接口方法的SQL语句,以及如何在单元测试中测试自定义的SQL语句,并展示了测试结果。
3、Mybatis-Plus 自定义sql语句
|
6月前
|
SQL Java 数据库连接
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
【YashanDB 知识库】解决 mybatis 的 mapper 文件 sql 语句结尾加分号";"报错
|
6月前
|
SQL 缓存 Java
框架源码私享笔记(02)Mybatis核心框架原理 | 一条SQL透析核心组件功能特性
本文详细解构了MyBatis的工作机制,包括解析配置、创建连接、执行SQL、结果封装和关闭连接等步骤。文章还介绍了MyBatis的五大核心功能特性:支持动态SQL、缓存机制(一级和二级缓存)、插件扩展、延迟加载和SQL注解,帮助读者深入了解其高效灵活的设计理念。
|
7月前
|
SQL XML Java
九、MyBatis动态SQL
九、MyBatis动态SQL
89 2
|
6月前
|
SQL XML Java
六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性
六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性
150 0
|
8月前
|
SQL Java 数据库连接
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
831 6
|
9月前
|
SQL XML Java
mybatis实现动态sql
MyBatis的动态SQL功能为开发人员提供了强大的工具来应对复杂的查询需求。通过使用 `<if>`、`<choose>`、`<foreach>`等标签,可以根据不同的条件动态生成SQL语句,从而提高代码的灵活性和可维护性。本文详细介绍了动态SQL的基本用法和实际应用示例,希望对您在实际项目中使用MyBatis有所帮助。
449 11