当前位置: 首页 > article >正文

#{}和${}

总结:

#{}:先编译sql语句,再给占位符传值,底层是PreparedStatement实现。可以防止sql注入,比较常用。

${}:先进行sql语句拼接,然后再编译sql语句,底层是Statement实现。存在sql注入现象。只有在需要进行sql语句关键字拼接的情况下才会用到。

#{}的使用场景:

#{} 的工作机制:

MyBatis 会将 #{} 中的参数替换为 SQL 预编译语句 的占位符(即 ?),然后将参数通过 JDBC 预编译的方式传递给数据库。

Mapper 接口

public interface CarMapper {
    List<Car> selectByCarType(String carType);
}

XML 配置

<select id="selectByCarType" resultType="com.powernode.mybatis.pojo.Car">
    select
        id, car_num as carNum, brand, guide_price as guidePrice, 
        produce_time as produceTime, car_type as carType
    from
        t_car
    where
        car_type = #{carType}
</select>

Service 层调用

List<Car> cars = carMapper.selectByCarType("SUV");

在这里,"SUV" 这个参数会通过 MyBatis 的 #{} 绑定机制,替换到 SQL 语句中的占位符 ? 处,然后执行查询。

MyBatis 转换后的 SQL:

在 MyBatis 运行过程中,这段 SQL 会被转换成如下形式:

select
    id, car_num as carNum, brand, guide_price as guidePrice, 
    produce_time as produceTime, car_type as carType
from
    t_car
where
    car_type = ?

实际执行过程:

假设用户调用了如下 Java 代码:

List<Car> cars = carMapper.selectByCarType("SUV");

在实际执行时,JDBC 会生成如下的最终 SQL 语句,并将 "SUV" 参数绑定到 ? 占位符:

select
    id, car_num as carNum, brand, guide_price as guidePrice, 
    produce_time as produceTime, car_type as carType
from
    t_car
where
    car_type = 'SUV';

${}:

${} 的使用和 #{} 不同,它是直接拼接参数到 SQL 语句中,而不是作为 JDBC 预编译的占位符因此,${} 具有一定的风险(SQL 注入),但在某些场景下它仍然是有用的。

1. ${} 的工作原理

  • ${} 会将参数的值直接拼接到 SQL 语句中,在 SQL 执行前完成字符串替换。
  • 它不经过预编译,因此无法避免 SQL 注入风险。

示例:使用 ${} 拼接参数

<select id="selectByCarType" resultType="com.powernode.mybatis.pojo.Car">
    select
        id, car_num as carNum, brand, guide_price as guidePrice, 
        produce_time as produceTime, car_type as carType
    from
        t_car
    where
        car_type = ${carType}
</select>

如果 Java 代码中传入参数为 "SUV"

carMapper.selectByCarType("SUV");

执行的 SQL 语句会被拼接成:

select
    id, car_num as carNum, brand, guide_price as guidePrice, 
    produce_time as produceTime, car_type as carType
from
    t_car
where
    car_type = SUV;

这条 SQL 会出错,因为它缺少引号来包裹字符串类型的值。根据 SQL 规范,SQL 语句中,字符串类型的值(如 "SUV")必须用 单引号 ' 包裹起来,否则会报语法错误。

如何解决报错?

加上单引号即可

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.powernode.mybatis.mapper.CarMapper">
    <select id="selectByCarType" resultType="com.powernode.mybatis.pojo.Car">
        select
            id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
        from
            t_car
        where
            <!--car_type = #{carType}-->
            <!--car_type = ${carType}-->
            car_type = '${carType}'
    </select>
</mapper>

${} 的适用场景 :

需求:通过向sql语句中注入asc或desc关键字,来完成数据的升序或降序排列。

CarMapper接口:

List<Car> selectAll(String ascOrDesc);

CarMapper.xml文件:

<select id="selectAll" resultType="com.powernode.mybatis.pojo.Car">
  select
  id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
  from
  t_car
  order by carNum #{key}
</select>

测试程序 

@Test
public void testSelectAll(){
    CarMapper mapper = (CarMapper) SqlSessionUtil.openSession().getMapper(CarMapper.class);
    List<Car> cars = mapper.selectAll("desc");
    cars.forEach(car -> System.out.println(car));
}

采用这种方式传值,最终sql语句会是这样:

select 
    id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType 
from t_car order by carNum 'desc'

 desc是一个关键字,不能带单引号的,所以在进行sql语句关键字拼接的时候,必须使用${}!!

使用${} 改造  :

<select id="selectAll" resultType="com.powernode.mybatis.pojo.Car">
  select
  id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
  from
  t_car
  <!--order by carNum #{key}-->
  order by carNum ${key}
</select>

批量删除

需求:一次删除多条记录。

对应的sql语句:

  • delete from t_user where id = 1 or id = 2 or id = 3;

  • delete from t_user where id in(1, 2, 3);

 我们到底需要选择#{}还是${}呢?

正确选择应该是${},因为选择#{},sql语句会变成delete from t_user where id in('1,2,3')  执行错误:1292 - Truncated incorrect DOUBLE value: '1,2,3'

正确写法:

<delete id="deleteBatch">
  delete from t_car where id in(${ids})
</delete>

对应的接口:

/**
     * 根据id批量删除
     * @param ids
     * @return
     */
int deleteBatch(String ids);

模糊查询:

查询奔驰系列的汽车。【只要品牌brand中含有奔驰两个字的都查询出来。】

使用${}

/**
     * 根据品牌进行模糊查询
     * @param likeBrank
     * @return
     */
List<Car> selectLikeByBrand(String likeBrank);
<select id="selectLikeByBrand" resultType="Car">
  select
  id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
  from
  t_car
  where
  brand like '%${brand}%'
</select>

对应的sql语句:

  select
  id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
  from
  t_car
  where
  brand like '%宝马%'
@Test
public void testSelectLikeByBrand(){
    CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
    List<Car> cars = mapper.selectLikeByBrand("奔驰");
    cars.forEach(car -> System.out.println(car));
}

使用#{}

第一种:concat函数
​
<select id="selectLikeByBrand" resultType="Car">
  select
  id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
  from
  t_car
  where
  brand like concat('%',#{brand},'%')
</select>

​
第二种:双引号方式(比较常用)
<select id="selectLikeByBrand" resultType="Car">
  select
  id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType
  from
  t_car
  where
  brand like "%"#{brand}"%"
</select>


http://www.kler.cn/news/361621.html

相关文章:

  • MySQL中localhost和127.0.0.1的区别
  • MacPro M3无法运行minikube 和 docker
  • 达梦数据库DEXP/DIMP逻辑备份还原
  • flask 接口还在执行中,前端接收到接口请求超时,解决方案
  • QT的文件操作类 QFile
  • 【java】抽象类和接口(了解,进阶,到全部掌握)
  • TemporalBench:一个专注于细粒度时间理解的多模态视频理解的新基准。
  • 软件开发术语(A开头)---持续更新
  • JavaScript 中,要实现清零操作
  • Leetcode—194. 转置文件【中等】(Shell)
  • 实验:使用Oxygen发布大型手册到Word格式
  • Vlan虚拟局域网
  • 读hunter_bipedal_control-main
  • MySQL事务及实现原理
  • 快速修改DBeaver快捷键设置
  • Jupyter Notebook中 Save and Export Notebook As不显示选项
  • C++ [项目] 飞机大战
  • word删除空白页 | 亲测有效
  • 专利交易:创新成果的桥梁
  • 数据结构实验:实现二叉树的各种基本运算的算法
  • 使用python绘制图表
  • node和npm版本冲突
  • Java-如果你的目标是从一个包含多个 Map 的 List 中统计所有 Map 中特定键(例如 “name“)的值,并将这些值组成一个新的 List
  • “网络协议入门:HTTP通信的四大组成部分“
  • 4步教你绘制流程图,轻松提高工作效率!
  • python+大数据+基于spark的短视频推荐系统【内含源码+文档+部署教程】