实际开发中SQL语句的参数值是不能写死到配置文件中的
,应该由前端发起的请求中包含的请求参数中的数据决定
<insert id="insertCar">
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
values(null,'1003','丰田霸道',30.0,'2000-10-11','燃油车');
insert>
JDBC当中的占位符
在JDBC中使⽤?
作为占位符,在程序的执行过程中,我们需要手动给SQL语句中的占位符传值
String sql = "insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,?,?,?,?,?)";
ps = conn.prepareStatement(sql);
// 给?传值
ps.setString(1,"103");
ps.setString(2,"奔驰E300L");
ps.setDouble(3,50.3);
ps.setString(4,"2022-01-01");
ps.setString(5,"燃油⻋");
// 执行SQL语句
int count = ps.executeUpdate();
MyBatis中的占位符
#{}底层使用的是PreparedStatement对象
:SQL语句中含有占位符,先对SQL语句进行预编译,然后获取值给SQL语句中的占位符 ?
传值, 可以避免SQL注入的风险
占位符?
传值的时候会原封不动地把值传过去(包括值的引号),即使用户提供的信息中含有sql语句关键字也无法参与编译过程
,最终被当作普通的字符处理${}底层使用的是Statement对象
: 直接将获取的值拼接到SQL语句当中,然后对拼接好的SQL语句进行编译,这样做存在SQL注入的风险
对于#{}(可以避免SQL注入的风险)
和${}(可以进⾏SQL语句关键字拼接)
底层都会根据条件自动获取对应的值然后为占位符赋值,最后将获取到值传给SQL语句
<insert id="insertCar">
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
values(null,#{carNum},#{brand},#{guidePrice},{produceTime},#{carType});
insert>
数据的升序或降序
需求:通过向SQL语句中注⼊asc或desc关键字
来完成查询数据的升序或降序排列
public interface CarMapper {
// 查询所有的汽车信息
List<Car> selectAllByAscOrDesc(String ascOrDesc);
}
public class CarMapperTest {
@Test
public void testSelectAllByAscOrDesc(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.selectAllByAscOrDesc("desc");
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}
}
使用#{}
会将获取到的SQL关键字(含引号)
赋值给占位符?
,这样会报SQL语法错误
<select id="selectAllByAscOrDesc" resultType="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>
**使用${}
可以将获取到的SQL关键字
直接拼接到SQL语句当中完成数据的升序或降序 **
<select id="selectAllByAscOrDesc" resultType="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>
拼接表名
实际开发中表的数据量非常庞大,如果将所有数据都存在一张表中的话会导致表的查询效率比较低(扫描的数据量太大),所以需要将这些数据有规律的分表存储
日志表
是专门用来存储日志信息的表,如果只有一张日志表,随着每天日志的增加表中的数据会越来越多,所以需要每天生成一个日志表如以当天日期作为表名称
需求: 前端在进行查询的时候会提交⼀个具体的⽇期,后端根据这个日期动态拼接得到一个表名
,最后将这个表名拼接到SQL语句中查询表中的数据
public class Log {
private Integer id;
private String log;
private String time;
//setter和getter方法
@Override
public String toString() {
return "Log{" +
"id=" + id +
", log='" + log + '\'' +
", time='" + time + '\'' +
'}';
}
}
public interface LogMapper {
// 根据日期名查询不同的表,获取表中所有的日志
List<Log> selectAllByTable(String date);
}
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));
}
}
使用#{}
的方式会将获取到的表名(含引号)
赋值给占位符?
,这样会报SQL语法错误
<mapper namespace="com.powernode.mybatis.mapper.LogMapper">
<select id="selectAllByTable" resultType="Log">
select * from t_log_#{date}
select>
mapper>
使用${}
的方式将获取到的表名
直接拼接到SQL语句之后
<mapper namespace="com.powernode.mybatis.mapper.LogMapper">
<select id="selectAllByTable" resultType="Log">
select * from t_log_${date}
select>
mapper>
批量删除(in的方式)
批量删除时可以使用or
或in
or
:delete from t_car where id=1 or id=2 or id=3;in
:delete from t_car where id in(1,2,3);需求: 使用in
关键字批量删除多条记录
public interface CarMapper {
//根据id批量删除
int deleteBatch(String ids);
}
@Test
public void testDeleteBatch(){
CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
int count = mapper.deleteBatch("1,2,3");
System.out.println("删除了⼏条记录:" + count);
SqlSessionUtil.openSession().commit();
}
使用#{}
的方式会将获取到的所有Id(含引号)
赋值给占位符?
,这样会报SQL语法错误
<delete id="deleteBatch">
delete from t_car where id in(#{ids})
delete>
使用${}
的方式将获取到的所有Id
直接拼接到SQL语句之后
<delete id="deleteBatch">
delete from t_car where id in(${ids})
delete>