1、statement接口:
statement接口用于向数据库发送SQL语句,该接口提供了三种执行SQL语句的方法:
boolean execute(String sql):运行语句,返回是否有结果集
ResultSet executeQuery(String sql):运行select语句,返回结果集
int executeUpdate(String sql):运行insert/update/delete语句,返回更新的行数
2、PreparedStatement接口:
该接口继承自Statement接口,用于执行预编译的Sql语句,该接口提供了对数据库进行基本操作的方法:
ResultSet executeQuery(String sql):运行select语句,返回结果集
int executeUpdate(String sql):运行insert/update/delete语句,返回更新的行数
void addBatch(String sql):把多条sql语句放入一个批处理种
int executeBatch(String sql):向数据库发送一批sql语句执行
3、PreparedStatement接口的优越性:
- 能够执行参数化的sql语句:开发人员能够通过修改梣属反复调用同一个sql语句,这样避免反复书写相同的sql语句的繁琐
- 比Statement效率更高:因为数据库系统对sql语句进行编译预处理,执行计划就会被缓存起来,该语句就能在将来的查询中重用,这样一来,它比statement对象生成的查询速度更快,性能更好,为了减少数据库的负载,实际应用中多使用preparedstatement
- preparedStatement可以防止SQL注入攻击:在使用参数查询的情况下,数据库系统不会将参数的内容视为sql指令的一部分来处理,而是在数据库完成sql指令的编译后,才套用参数执行。
4、sql注入:
sql注入是比较常用的网络攻击方式,它利用现有程序的漏洞,将恶意的sql命令注入到后台数据库,最终达到欺骗服务器并实现攻击者意图的目的。在程序的运行中,sql注入会造成数据库信息泄露,网页被篡改等问题.
接下来通过一个简单的示例来说明sql注入发生的过程。如果在某个系统的登录模块中有如下的验证权限的语句:
select * from 用户表 where name=用户输入的用户名 and password=用户输入的密码;
正常情况下:用户需要输入正确的用户名和密码才能完成登录,但是,如果出现下面这种情况:
select * from 用户表 where name=用户输入的用户名 and password=用户输入的密码 or 1=1;
此时,上述的查询基本失效,因为无论密码对错,用户均可以成功登录,使得程序出现安全隐患,这就是sql注入的一个具体场景。
下面分别是Statement接口和Preparedstatement接口的应用场景:
1.通过使用Statement接口来查询表种数据:
package com.jdbc.bookone;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JdbcOne {
public static void main(String[] args) {
try{
//加载并注册数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接
Connection connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/MF","root","root");
//获取sql语句执行者
Statement statement=connection.createStatement();
//执行sql语句
ResultSet resultSet=statement.executeQuery("select * from student");
//操作结果集
while(resultSet.next()){
System.out.println("姓名: "+resultSet.getString("sName")+" 年龄:"+resultSet.getInt("sAge"));
}
//回收数据库资源
connection.close();
statement.close();
resultSet.close();
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
2、通过使用PreparedStatement接口来查询表中数据和向表中插入数据:
package com.jdbc.bookone;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JdbcTwo {
public static void main(String[] args) {
// TODO Auto-generated method stub
//加载驱动
try{
Class.forName("com.mysql.jdbc.Driver");
//获取连接
Connection connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/MF","root","root");
//获取sql语句的执行者并执行sql
PreparedStatement preparedStatement=connection.prepareStatement("select * from student");
//操作结果集
ResultSet rs=preparedStatement.executeQuery();
while(rs.next()){
System.out.println(rs.getString("sAge"));
}
preparedStatement=connection.prepareStatement("insert into student(sID,sName,sAge) values(?,?,?)");
preparedStatement.setString(1, "0010");
preparedStatement.setString(2, "jack");
preparedStatement.setInt(3, 40);
preparedStatement.executeUpdate();
while(rs.next()){
System.out.println(rs.getString("sName"));
}
connection.close();
preparedStatement.close();
rs.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
3、通过使用PreparedStatement接口来向表中一次插入多条数据:
package com.jdbc.bookone;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class JdbcThree {
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
Class.forName("com.mysql.jdbc.Driver");
Connection connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/MF","root","root");
PreparedStatement preparedStatement=connection.prepareStatement("insert into student(sID,sName,sAge) values(?,?,?)");
for(int i=0 ;i<5;i++){
preparedStatement.setString(1,"010");
preparedStatement.setString(2, "jack");
preparedStatement.setInt(3, 8+i);
preparedStatement.addBatch();
if(i%10==0){
preparedStatement.executeBatch();
preparedStatement.clearBatch();
}
connection.close();
preparedStatement.close();
}
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}