JDBC中的PreparedStatement与Statement

Statement 和 PreparedStatement 都是JDBC中用于执行静态SQL语句并返回其生成的结果的对象,他们之间的关系是什么?在使用上有哪些差别?

JDBC访问数据库的过程

在利用JDBC访问数据库的过程中,本质上我们还是执行sql语句来对数据库表数据进行操作,JDBC是连接java程序和数据库之间的一座桥梁,承担着连接数据库,执行sql,并返回执行结果的任务。

JDBC访问数据库的过程如下:

 

在获取到与数据库之间的连接之后,我们需要创建Statement对象,来执行我们编写的SQL语句,并返回相应结果,对于查询语句来说,还需要一个ResultSet对象来接收查询结果集;对于增删改来说,本质上都是对数据表的更新操作,是没有返回结果集的。

Statement操作数据表的弊端

(1)sql存在字符串拼接操作,比较繁琐

(2)存在SQL注入问题(安全漏洞

案例演示:

假设需要进行用户登录验证,将控制台输入的账号密码和数据库表中存在的用户信息进行比对,用户存在且密码正确,则显示登陆成功。

还是如下用户登录功能,目的是检测用户输入的账号密码是否存在,存在则返回一个user对象,并打印登录信息。

数据库用户表数据如下:

当输入如下内容时,数据库明显不存在对应用户,但是却返回了user对象

原因,控制台输入后拼接的sql为

可以看到以上sql在拼接之后,'1'='1'条件始终为真,那么就会绕过身份验证,返回所有用户的数据,因为在识别sql的过程中错误的解析了用户输入。

SQL注入问题的解决办法

对于 Java 而言,要防范 SQL 注入,只要用 PreparedStatement(从Statement扩展而来) 取代 Statement 就可以了。

PreparedStatement

PreparedStatement 是继承自 Statement的一个子接口,是对Statement的一个拓展。

PreparedStatement 提供了一种更安全和更有效的方式来执行参数化查询。

PreparedStatement 使用占位符(?)来表示参数,然后将参数值与查询分离开来,通过占位符的标记,程序在执行的过程中可以明确的识别占位符的位置就是一个参数,避免了sql拼接带来的错误识别问题,这样可以防止 SQL 注入攻击。

执行效率对比

在传入sql创建PreparedStatement 对象时,会进行预编译,DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。

而statement对象中,即使是相同操作,但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义,数据库不会对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次,效率较低。

除此之外,在操作BLOB类型的数据时,必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的。

BLOB类型可以用来存储各种类型的二进制数据,例如图像、音频、视频、文档等。

小结

Statement 适用于静态查询和简单查询,没有动态设置参数的需求。

PreparedStatement 适用于需要设置参数的查询和重复执行的查询,且拥有更好的安全性,性能也更好。

在实际使用过程中,推荐使用PreparedStatement来对数据库进行操作,避免sql注入带来的数据安全问题,同时,在执行多次动态操作时,PreparedStatement的效率更高。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值