Statement 和 PreparedStatement以及sql注入
Statement 和 PreparedStatement以及sql注入
Statement 和 PreparedStatement之间的关系和区别.
关系:PreparedStatement继承自Statement,都是接口
区别:PreparedStatement可以使用占位符,是预编译的,批处理比Statement效率高
详解:
1、PreparedStatement:表示预编译的 SQL 语句的对象。
接口:public interface PreparedStatement extends Statement之间的继承关系
SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。
注意:
占位符 设置参数类型 与已知sql类型相同 setInt、setString setObject问号 第一个问号为1 第二个为2 依次类推…
例子:
PreparedStatement pstmt = con.prepareStatement("UPDATE student name = ? where id= ?");
pstmt.setString(1,”张三”)
pstmt.setInt(2, 1002)
pstmt.execute()//注意提交时这里不能再有sql语句,不同于Statement
2、Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。
接口:public interface Statement extends Wrapper
在默认情况下,同一时间每个 Statement 对象只能打开一个 ResultSet 对象。因此,如果读取一个 ResultSet 对象与另一个交叉,则这两个对象必须是由不同的 Statement 对象生成的。如果存在某个语句的打开的当前 ResultSet 对象,则 Statement 接口中的所有执行方法都会隐式关闭它。
如以下操作:创建statement对象
Statement stat=conn.createStatement();
String sql="insert into student values(1002,'张三',to_date('21-9-2016','dd-mm-yyyy'))";
stat.execute(sql);//这里提交时应该有sql语句,不同于PreparedStatment
附:
Statement 对象用于执行不带参数的简单 SQL 语句,类似于硬编码;PreparedStatement 对象用于执行带或不带参数的预编译 SQL 语句;CallableStatement 对象用于执行对数据库已存储过程的调用。
总结如下:
Statement每次执行sql语句,数据库都要执行sql语句的编译,最好用于仅执行一次查询并返回结果的情形,效率高于PreparedStatement.但存在sql注入风险。
PreparedStatement是预编译执行的。在执行可变参数的一条SQL时,PreparedStatement要比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率高。安全性更好,有效防止SQL注入的问题。对于多次重复执行的语句,使用PreparedStatement效率会更高一点。执行SQL语句是可以带参数的,并支持批量执行SQL。由于采用了Cache机制,则预编译的语句,就会放在Cache中,下次执行相同的SQL语句时,则可以直接从Cache中取出来。
String sql = "delete from tb_book where id="+id;
PreparedStatement pst = conn.prepareStatement(sql);
pst.execute(sql);//拼接的参数需要加sql
sql注入
什么是SQL注入,怎么防止SQL注入?
所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
正常语句:
select id from users where username = '123 and password = '123'
sql注入语句:
那么如果我们在用户名处输入'or 1=1-- 而密码随便输入个456呢? 我们来看看数据库中的查询语句:
select id from users where username = '' or 1=1-- and password = '456'
'又 这里呢1=1永远为真,后面 and password = '456'被注释掉了。数据库不需要考虑,这里我们就跳过了验证。
怎么防止SQL注入
使用存储过程来执行所有的查询;
检查用户输入的合法性;
将用户的登录名、密码等数据加密保存。
Sql语句拼接 “+book.getId()+”
//编写sql语句-
String sql="select * from tb_book where 1=1";
//根据 id name 模糊查询 1=1为了拼接
if(book.getId()!=null && !book.getId().equals("")){
sql+=" and id='"+book.getId()+"'";
}
if(book.getName()!=null && !book.getName().equals("")){
sql+=" and name like '%"+book.getName()+"%'";
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!