JDBC—03—SQL注入问题;PreparedStatement介绍;JDBC的事务处理


一、 JDBC的使用

 

9.SQL 注入问题

9.1什么是 SQL 注入

所谓 SQL 注入,就是通过把 `含有 SQL 语句片段的参数` 插入到需要执行的 SQL 语句中,然后statement把SQL语句发送到数据库中, 数据库进行编译, 最终达到欺骗数据库服务器执行恶意操作的 SQL 命令。

9.2如何解决?

因为statement没有SQL语句预编译的能力, 所以会是数据库执行到恶意SQL命令;

我们换一个有预编译能力的statement对象就行了---PreparedStatement;

 

 

 

10.PreparedStatement 对象的使用(重点)

(1)PreparedStatement 特点:

  • PreparedStatement 接口继承 Statement 接口
  • PreparedStatement 效率高于 Statement
  • PreparedStatement 支持动态绑定参数
  • PreparedStatement 具备 SQL 语句预编译能力, 所以使用 PreparedStatement 可防止出现 SQL 注入问题

(2) 通过 PreparedStatement 对象向表中插入数据:

向 Departments 表中插入一条数据:


conn = JdbcUtil.getConnection();
//再也不用拼接字符串或者参数了, 参数用占位符`?`表示, 然后在单独对占位符赋值就好了; 
ps = conn.prepareStatement("insert into departmentsvalues(default,?,?)");
ps.setString(1, departmentName);
ps.setInt(2, locationId);
ps.execute();

 

 

 

11. PreparedStatement 的预编译能力

11.1什么是预编译

(1)SQL 语句的执行步骤

  • 语法和语义解析
  • 优化 sql 语句,制定执行计划
  • 执行并返回结果

但是很多情况,我们的一条 sql 语句可能会反复执行,或者每次执行的时候只有个别的值不同(比如 select 的 where 子句值不同,update 的 set 子句值不同,insert 的 values 值不同)。如果每次都需要经过硬解析----上面的词法语义解析、语句优化、制定执行计划等,那效率就明显不行了。

所谓预编译语句就是将这类语句中的值用占位符替代,可以视为将 sql 语句模板化或者说参数化;

预编译语句的优势在于:一次编译、多次运行,省去了解析优化等过程(将完全硬解析变成了硬软都有);此外预编译语句能防止 sql 注入;

(2)解析过程

  • 硬解析:在不开启缓存执行计划的情况下,每次 SQL 的处理都要经过:语法和语义的解析,优化器处理 SQL,生成执行计划。整个过程我们称之为硬解析。
  • 软解析如果开启了缓存执行计划,数据库在处理 sql 时会先查询缓存中是否含有与当前SQL语句相同的执行计划,如果有则直接执行该计划。(我们所谓的预编译也就是软解析;)

11.2预编译方式

  • 开始数据库的日志
  • show VARIABLES like '%general_log%'
  • set GLOBAL general_log = on
  • set GLOBAL log_output='table'

(1)依赖数据库驱动完成预编译

如果我们没有开启数据库服务端编译,那么默认的是使用数据库驱动完成 SQL 的预编

译处理。

(2)依赖数据库服务器完成预编译

我们可以通过修改连接数据库的 URL 信息,添加 useServerPrepStmts=true 信息开启服

务端预编译。

 

 

 

12. 通过 PreparedStatement 对象完成数据的更新

代码

更新数据

conn = JdbcUtil.getConnection();

ps = conn.prepareStatement("update departments set

department_name = ?,location_id = ? where department_id = ?");

ps.setString(1, departmentName);

ps.setInt(2, localhostId);

ps.setInt(3, departmentId);

ps.execute();

 

 

 

13. 通过 PreparedStatement 对象完成数据的查询

(1)查询返回单条结果集


conn = JdbcUtil.getConnection();

ps = conn.prepareStatement("select * from

departments where department_id = ?");

ps.setInt(1, departmentId);

rs = ps.executeQuery();

while(rs.next()){

dept=new Departments();

dept.setDepartmentId(rs.getInt("department_id"));

dept.setDepartmentName(rs.getString("department_name"));

dept.setLocationId(rs.getInt("location_id"));

}

 

(2)查询返回多条结果集

建立了一个集合而已, 然后不断地输出这个集合的信息就可以了; 

JDBC—03—SQL注入问题;PreparedStatement介绍;JDBC的事务处理_第1张图片

 

 

 

 

 上图有个bug,  大家可以试着找找看;

JDBC—03—SQL注入问题;PreparedStatement介绍;JDBC的事务处理_第2张图片

JDBC—03—SQL注入问题;PreparedStatement介绍;JDBC的事务处理_第3张图片

既然是模糊查询, 怎么能用`=`, 应该用 `like`;

 

 

 

 

 

14. PreparedStatement 批处理操作

批处理:在与数据库的一次连接中,批量的执行条 SQL 语句。

代码:

注意:addBatch()和executeBatch();

JDBC—03—SQL注入问题;PreparedStatement介绍;JDBC的事务处理_第4张图片

 

 

 

 

 

 

15. JDBC 中的事务处理

在 JDBC 操作中数据库事务默认为自动提交。

如果事务需要修改为手动提交,那么我们需要使用 Connection 对象中的 setAutoCommit 方法来关闭事务自动提交, 然后通过Connection 对象中的 commit 方法与 rollback 方法进行事务的提交与回滚。

 

你可能感兴趣的:(JDBC—03—SQL注入问题;PreparedStatement介绍;JDBC的事务处理)