1. #{ }和${ }的区别 67
#{}:先编译sql语句,再给占位符传值,底层是PreparedStatement实现。可以防⽌sql注⼊,⽐较常⽤。
${}:先进⾏sql语句拼接,然后再编译sql语句,底层是Statement实现。存在sql注⼊现象。只有在需要进⾏sql语句关键字拼接的情况下才会⽤到。
2 初步认识#{ }和${ }的区别 67
2.1 需求:根据car_type查询汽⻋ 67
接口CarMapper
package com.powernode.mybatis.mapper;
import com.powernode.mybatis.pojo.Car;
import java.util.List;
//这是一个接口 演示 #{ }和${ }的区别 67
public interface CarMapper {
/**
* 插入Car信息,并且使用生成的主键值。
* @param car
* @return
*/
int insertCarUseGeneratedKeys(Car car);
/**
* 根据汽车品牌进行模糊查询
* @param brand
* @return
*/
List selectByBrandLike(String brand);
/**
* 批量删除,根据id
* @param ids
* @return
*/
int deleteBatch(String ids);
/**
* 查询所有的汽车信息。然后通过asc升序,desc降序。
* @param ascOrDesc
* @return
*/
List selectAllByAscOrDesc(String ascOrDesc);
/**
* 根据汽车类型获取汽车信息。
* @param carType
* @return
*/
List selectByCarType(String carType);
}
test中com.powernode.mybatis.test
CarMapperTest类中的testSelectByCarType
@Test
public void testSelectByCarType(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List cars = mapper.selectByCarType("新能源");
//遍历
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}
CarMapper.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>
2.1.1 #{}的执行结果: 67
[main] DEBUG c.p.mybatis.mapper.CarMapper.selectByCarType - ==> Preparing: 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 = ?
[main] DEBUG c.p.mybatis.mapper.CarMapper.selectByCarType - ==> Parameters: 新能源(String)
[main] DEBUG c.p.mybatis.mapper.CarMapper.selectByCarType - <== Total: 2
2.1.2 ${}的执行结果: 67
[main] DEBUG c.p.mybatis.mapper.CarMapper.selectByCarType - ==> Preparing: 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 = 新能源
[main] DEBUG c.p.mybatis.mapper.CarMapper.selectByCarType - ==> Parameters:
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown column '新能源' in 'where clause'
### The error may exist in CarMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### 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 = 新能源
### Cause: java.sql.SQLSyntaxErrorException: Unknown column '新能源' in 'where clause'
2.1.3 #{}和${}的区别: 67
#{}: 底层使用PreparedStatement。特点:先进行SQL语句的编译,然后给SQL语句的占位符问号?传值。可以避免SQL注入的风险。
${}:底层使用Statement。特点:先进行SQL语句的拼接,然后再对SQL语句进行编译。存在SQL注入的风险。
优先使用#{},这是原则。避免SQL注入的风险。
3. 使用sql排序看看#{}和${}的区别 68
//查询所有 排序 68
@Test
public void testSelectAllByAscOrDesc(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.selectAllByAscOrDesc("asc");//升序
//List<Car> cars = mapper.selectAllByAscOrDesc("desc");//降序
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}
CarMapper.xml
<select id="selectAllByAscOrDesc" 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
produce_time ${ascOrDesc}
</select>
3.1 #{}的执行结果: 68
Preparing: select
id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType
from t_car order by produce_time ?
Parameters: asc(String)
select
id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType
from t_car order by produce_time 'asc'
3.2 ${}的执行结果: 68
Preparing:
select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType
from t_car order by produce_time asc
Parameters:
如果需要SQL语句的关键字放到SQL语句中,只能使用${},因为#{}是以值的形式放到SQL语句当中的。
4. 向SQL语句当中拼接表名,就需要使用${} 69
现实业务当中,可能会存在分表存储数据的情况。因为一张表存的话,数据量太大。查询效率比较低。可以将这些数据有规律的分表存储,这样在查询的时候效率就比较高。因为扫描的数据量变少了。
日志表:专门存储日志信息的。如果t_log只有一张表,这张表中每一天都会产生很多log,慢慢的,这个表中数据会很多。
怎么解决问题?
可以每天生成一个新表。每张表以当天日期作为名称,例如:
t_log_20220901
t_log_20220902
....
4.1 你想知道某一天的日志信息怎么办? 69
假设今天是20220901,那么直接查:t_log_20220901的表即可。
test中com.powernode.mybatis.test
LogMapperTest
package com.powernode.mybatis.test;
import com.powernode.mybatis.mapper.LogMapper;
import com.powernode.mybatis.pojo.Log;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
//向SQL语句当中拼接表名,就需要使用${} 69
//想知道某一天的日志信息
public class LogMapperTest {
@Test
public void testSelectAllByTable(){
SqlSession sqlSession = SqlSessionUtil.openSession();
LogMapper mapper = sqlSession.getMapper(LogMapper.class);
List<Log> logs = mapper.selectAllByTable("20220901");
logs.forEach(log -> System.out.println(log));
}
}
main中com.powernode.mybatis.mapper
接口LogMapper
package com.powernode.mybatis.mapper;
import com.powernode.mybatis.pojo.Log;
import java.util.List;
public interface LogMapper {
List<Log> selectAllByTable(String date);
}
LogMapper.xml
<?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">
<!--namespace不能使用别名机制。必须写全限定接口名称。带有包名的。-->
<mapper namespace="com.powernode.mybatis.mapper.LogMapper">
<select id="selectAllByTable" resultType="com.powernode.mybatis.pojo.Log">
<!--select * from t_log_#{date}-->
select * from t_log_${date}
</select>
</mapper>
原理很简单,如果你需要先进行sql拼接在进行编译的就用${ }
如果你就只需要进行传值用#{ }
5. 批量删除 70
批量删除:一次删除多条记录。
批量删除的SQL语句有两种写法:
第一种or:delete from t_car where id=1 or id=2 or id=3;
第二种int:delete from t_car where id in(1,2,3);
应该采用${}的方式:
delete from t_car where id in(${ids});
test中com.powernode.mybatis.test
CarMapperTest类中的testDeleteBatch
//批量删除 70
@Test
public void testDeleteBatch(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
int count = mapper.deleteBatch("11,12,13");
System.out.println(count);
sqlSession.commit();
sqlSession.close();
}
CarMapper.xml
<delete id="deleteBatch">
<!--delete from t_car where id in(#{ids})-->
delete from t_car where id in(${ids})
</delete>
6. 模糊查询:like 71
需求:根据汽车品牌进行模糊查询
select * from t_car where brand like '%奔驰%';
select * from t_car where brand like '%比亚迪%';
第一种方案:
'%${brand}%'
第二种方案:concat函数,这个是mysql数据库当中的一个函数,专门进行字符串拼接
concat('%',#{brand},'%')
第三种方案:比较鸡肋了。可以不算。
concat('%','${brand}','%')
第四种方案:
"%"#{brand}"%"
test中com.powernode.mybatis.test
CarMapperTest类中的testSelectByBrandLike
//模糊查询 71
@Test
public void testSelectByBrandLike(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.selectByBrandLike("奔驰");
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}
CarMapper.xml
<select id="selectByBrandLike" 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
<!--brand like '%${brand}%'-->
<!--brand like concat('%',#{brand},'%')-->
<!--brand like concat('%','${brand}','%')-->
brand like "%"#{brand}"%"
</select>