JDBC访问数据库的过程,sql注入问题预总结

package cn.mybats.jdbc;


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


/***
 * 
 * @author yzw
 *
 */
public class JdbcTest {


public static void main(String[] args) {
// --1.定义数据连接
Connection connection = null;


// --2.定义预处理(预处理就是将编译后的sql保存在数据库端的缓存中,如果之后的sql一样,就不用编译了,提高数据库性能)
PreparedStatement preparedStatement = null;
// --3.数据结果集
ResultSet resultSet = null;
try {
// --4.加载数据库驱动,驱动名称在数据库驱动jar包中
Class.forName("com.mysql.jdbc.Driver");
//--5.获取数据库连接,通过驱动管理类DriverManager,url,用户名,密码
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/study?characterEncoding=utf-8",
"root", "521125");
//--6.定义sql
String sql = "select * from test001 where t_name = ?";
//--7.sql被编译并且存储在preparedstatement中,更高效的多次访问sql
preparedStatement = connection.prepareStatement(sql);
//--8.填充参数
preparedStatement.setString(1, "yzw");
// --8.执行sql,并返回查询结果集
resultSet = preparedStatement.executeQuery();
// --9.遍历查询
while (resultSet.next()) {
System.out.println(resultSet.getString("t_id") + " " + resultSet.getString("t_name"));
}
// 1,执行效率:Statement 采取直接编译 SQL 语句的方式,扔给数据库去执行,而 PreparedStatement 则先将 SQL 语句预编译一遍,再填充参数,这样效率会高一些。JDK 文档说:SQL 语句被预编译并且存储在 PreparedStatement 对象中,其后可以使用该对象高效地多次执行该语句。 


// 2,代码可读性:Statement 中 SQL 语句中需要 Java 中的变量,加就得进行字符串的运算,还需要考虑一些引号、单引号的问题,参数变量越多,代码就越难看,而且会被单引号、双引号搞疯掉;而 PreparedStatement,则不需要这样,参数可以采用“?”占位符代替,接下来再进行参数的填充,这样利于代码的可读性,并且符合面向对象的思想。 


// 3,安全性:Statement 由于可能需要采取字符串与变量的拼接,很容易进行 SQL 注入攻击,而 PreparedStatement 由于是预 
// 编译,再填充参数的,不存在 SQL 注入问题。 
} catch (Exception e) {
e.printStackTrace();
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

}


问题一:Statement和PreparedStatement的区别

  先来说说,什么是java中的Statement:Statement是java执行数据库操作的一个重要方法,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句。具体步骤:

  1.首先导入java.sql.*;这个包。

  2.然后加载驱动,创建连接,得到Connection接口的的实现对象,比如对象名叫做conn。

  3.然后再用conn对象去创建Statement的实例,方法是:Statement stmt = conn.creatStatement("SQL语句字符串");

  Statement 对象用于将 SQL 语句发送到数据库中。实际上有三种 Statement 对象,它们都作为在给定连接上执行 SQL语句的包容器:Statement、PreparedStatement(它从 Statement 继承而来)和CallableStatement(它从 PreparedStatement 继承而来)。它们都专用于发送特定类型的 SQL 语句:Statement 对象用于执行不带参数的简单 SQL 语句;PreparedStatement 对象用于执行带或不带参数的预编译 SQL 语句;CallableStatement 对象用于执行对数据库已存储过程的调用。

  综上所述,总结如下:Statement每次执行sql语句,数据库都要执行sql语句的编译,最好用于仅执行一次查询并返回结果的情形,效率高于PreparedStatement.但存在sql注入风险。PreparedStatement是预编译执行的。在执行可变参数的一条SQL时,PreparedStatement要比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率高。安全性更好,有效防止SQL注入的问题。对于多次重复执行的语句,使用Prepared

Statement效率会更高一点。执行SQL语句是可以带参数的,并支持批量执行SQL。由于采用了Cache机制,则预编译的语句,就会放在Cache中,下次执行相同的SQL语句时,则可以直接从Cache中取出来。

PreparedStatement pstmt  =  con.prepareStatement("UPDATE EMPLOYEES  SET name= ? WHERE ID = ?");
pstmt.setString(1, "李四");
pstmt.setInt(2, 1);
pstmt. executeUpdate();

 

那么CallableStatement扩展了PreparedStatement的接口,用来调用存储过程,它提供了对于输入和输出参数的支持,CallableStatement 接口还有对 PreparedStatement 接口提供的输入参数的sql查询的支持。

PreparedStatement: 数据库会对sql语句进行预编译,下次执行相同的sql语句时,数据库端不会再进行预编译了,而直接用数据库的缓冲区,提高数据访问的效率(但尽量采用使用?号的方式传递参数),如果sql语句只执行一次,以后不再复用。

 从安全性上来看,PreparedStatement是通过?来传递参数的,避免了拼sql而出现sql注入的问题,所以安全性较好。
 在开发中,推荐使用 PreparedStatement

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值