首先看一下他们倆的创建方式
{
Connection connection = InitJdbcConnection.getConnection();
try {
Statement statement = connection.createStatement();
PreparedStatement preparedStatement = connection.prepareStatement("xxx");
} catch (SQLException e) {
e.printStackTrace();
}
}
- Statement 是通过createXX创建出来的, 动词+名词 Connection对象已经通过函数名告诉我们, Statement是有独立性的
- 对于一个Connection来说,一个Statement对象可以执行多条不同的SQL
- 对于一个Connection来说,一个Statement对象可以执行多条不同的SQL
- PreparedStatement 是直接点出来的, 其没有方法动词, 不知道的还能以为他是Connection的成员变量;但实际上他也是一个函数;
- Prepared 的直接意思就是 已经准备好的, 是形容词
- 对于一个Connection来说, PreparedStatement创建出来只能执行传递的一条SQL
再看一下 Statement 对象的函数
Statement 对象的函数都要传一下SQL进去, 他就是个SQL执行器,
如图,statement对象是通过数据库创建出来后, 就是一个sql执行器,一个statement可以执行多个SQL, 不支持参数预定义,可以用于执行固定的sql
为什么说 Statement 不能防止SQL注入? 比如我们要调用execute函数, 要给他传一个sql字符串进去,那么这整个字符串都一个可修改的变量, 假设这个字符串是业务动态拼接传递进来的, 想搞坏事的人给接口传了写奇奇怪怪的参数
SQL注入的例子
就是个例子别当真,我也没遇到过注入问题,都是理论,明白注入的道理就好
把main函数当成Web Ajax的入参解析;
SQL注入者成功拿到了目的数据, 顺手把你表删了,一点都不注重可持续发展;
而preparedStatement 在创建时就必须要为其赋值一个sql, 可以为其设置预定义值,所以preparedStatement一个对象只能服务一条sql,
你想想SQL的模板都定义好了,就是靠程序传些参数进去, 具体看下面描述;
为什么说PreparedStatement有防止SQL注入的功能
首先要理解什么是SQL注入, SQL注入的方式具体可以百度; 我这边白话一点的说, SQL注入就是给SQL拼字符串参数时加一些固定的SQL语法,比如注释--
,比如一些奇奇怪怪的SQL函数,比如关键字, 但是可以保证的是SQL注入能修改的点只有参数, 而PreparedStatement支持预定义参数, 这时候就可以给参数变量做校验,比如必须是Int类型,不是就报错, PreparedStatement对象设置参数是可以选择参数类型,而SQL注入一般都是字符类型;**
**如果非要抓着SQL注入这一点,**PreparedStatement的确比Statement好的,但你说Statement就不能我先校验一下SQL吗, 当然也可以,仁者见仁;
PreparedStatement还有什么好处吗?
就非要用这些核心的对象支持操作SQL吗1. 设计角度 :从逻辑上讲,Java的Connection对象对应 代码和DB之间的一条连接, 数据库执行一个链接执行SQL那是串行的, 并行只会发生在多个Connection之间; 你看Statement对象,假如就有人喜欢 create多个Statement, 然后Java的Thread一起跑呢, 其实这样也没关系, 因为Statement正在执行 execute (新增,编辑)操作的时候都给加了
synchronized
关键字,但就是怪怪的, 就好像哥几个去洗澡, 交钱的时候说可以一起玩, 到房间了又说只能一个个来; 怪哉
-
开发角度: 从基础的抽象原则, OO思想, 代码可维护性角度上来讲, 在代码里写字符串SQL已经很不人道了, 难道连不同类型的参数都要搞成String传进去吗, 非要这样为什么不试试存储过程呢? 效率比Java高,能省大量连接数, 连数据处理都可以让数据库自己去做; 所以PreparedStatement有个好处就是提供了参数类型API
-
支持DB的预编译
具体看这篇, 人家已经写的很好了, 这里不复述 https://www.cnblogs.com/micrari/p/7112781.html
总结
静态SQL可用Statement
复杂的动态的用PreparedStatement肯定不会错