mybatis 之 占位符#{} 和 ${}

本文详细解析了MyBatis中#{}

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. #{}占位符用来设置参数,参数的类型可以有3种,基本类型,自定义类型,map基本类型作为参数,参数与占位符中的名称无关。
    <select id="findById" parameterType="int" resultType="cn.wh.vo.Role">
            select * from t_role where id = #{xxxid}
        </select>

    测试:

    @Test
        public void testSelectOne(){
            Role role = (Role)session.selectOne("cn.wh.mapper.RoleMapper.findById",1);
            System.out.println(role.getName());
        }

    自定义类型作为参数,自定义类中需要为为属性提供get方法,如果没有提供get方法,那么会根据占位符中的名称去反射获取值,如果占位符中的名称和属性不一致,那么报ReflectionException。

    <select id="findListBypage" parameterType="cn.wh.util.PageUtil" resultType="Role">
            select * from t_role limit #{index},#{size}
        </select>

    测试:

    复制代码
    @Test
        public void testPage1(){
            PageUtil pu = new PageUtil();
            pu.setIndex(3);
            pu.setSize(3);
            List<Role> list = session.selectList("cn.wh.mapper.RoleMapper.findListBypage", pu);
            for(Role r:list){
                System.out.println(r.getName());
            }
        }
    复制代码

    Map作为参数类型,key和占位符中的名称一致即可,如果名称不一致那么将会把null,传递到占位符中。

    注意:#{}占位符不能解决一下 3 类问题:

    表名是动态的: Select * from #{table_name}

    列名是动态的:Select #{column_name} from t_role

    排序列是动态的: Select * from t_role order by #{columu}

 

 

  1. ${}占位符是字符串连接符,可以用来动态设置表明,列名,排序名

    ${}参数不能为基本数据类型,只能为自定义类型和map

    <!-- 查询所有 -->
        <select id="findAll" parameterType="map" resultType="cn.wh.vo.Role">
            select * from ${tableName}
        </select>

    测试:

    复制代码
    @Test
        public void testSelectList(){
            Map<String,String> map = new HashMap<String,String>();
            map.put("tableName", "t_role");
            List<Role> list = session.selectList("cn.wh.mapper.RoleMapper.findAll",map);
            for(Role role:list){
                System.out.println(role.getId()+"----"+role.getName());
            }
        }
    复制代码

    作为连接符使用:

    <select id="selectLike1" parameterType="map" resultType="Role">
            select *from t_role where name like '${name}%';
        </select>

    测试:

    复制代码
    @Test
        public void testLike2(){
            Map<String,String> map = new HashMap<String,String>();
            map.put("name", "黄");
            List<Role> list = session.selectList("cn.wh.mapper.RoleMapper.selectLike1",map);
            for(Role r:list){
                System.out.println(r.getName());
            }
        }
    复制代码
### MyBatis 中 `#` `$` 占位符的区别 #### 1. 工作原理差异 在 MyBatis 中,`#` `$` 都是用来在 SQL 语句中插入参数的占位符,但两者的工作原理不同。 对于 `#` 占位符而言,它会将传入的数据都当成字符串来处理,并自动加上单引号。这种方式可以有效防止 SQL 注入攻击[^1]。例如: ```sql SELECT * FROM users WHERE id = #{userId} ``` 而 `$` 占位符则不会对数据做任何特殊处理,而是直接将其作为原生字符串拼接到 SQL 语句中。这意味着如果输入未经严格校验,则可能存在安全风险[^3]。比如: ```sql SELECT * FROM users WHERE username LIKE &#39;%${username}%&#39; ``` #### 2. 应用场景对比 由于上述特性上的差别,这两种占位符适用于不同的场合。 当需要确保安全性并希望让 JDBC 自动处理类型转换时,应该优先考虑使用 `#` 占位符。这通常是在构建查询条件、更新操作等情况下非常适用的选择[^2]。 相反,若确实有必要动态地改变表名或列名等情况(尽管这种情况较为少见),那么此时可以选择使用 `$` 来实现更灵活的功能需求[^4]。不过需要注意的是,在这种情形下务必谨慎对待用户输入的内容,以免引发潜在的安全隐患。 #### 3. 实际应用案例展示 下面通过具体的例子进一步说明两者的区别及其应用场景: ##### 使用 `#` 的情况 假设有一个简单的查询请求,目的是获取指定 ID 的用户信息: ```xml <select id="getUserById" parameterType="int" resultType="User"> SELECT * FROM users WHERE id = #{id}; </select> ``` 这里采用 `#` 方式传递参数,既简单又安全可靠。 ##### 使用 `$` 的情况 再来看另一个复杂一点的例子——分页查询功能实现: ```xml <select id="getUsersByPage" parameterType="map" resultType="User"> SELECT * FROM users LIMIT ${offset},${limit}; </select> ``` 在这个场景里选择了 `${}` 形式的变量替换是因为 MySQL 的 `LIMIT` 子句不允许使用预编译参数形式(`?`)来进行偏移量数量设置;因此只能借助于 `${}` 进行动态注入。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值