总结:
#{}:先编译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> 
                


















