MySQL-JDBC入门与SQL注入
一.JDBC概述
1.JDBC
- 在Java语言中提供对数据库访问的支持
- Sun公司于1996年提供了一套访问数据库的标准Java类库JDBC
- JDBC的全称是Java数据库连接(Java Database Connectivity)它是一套用于执行 SQL语句的Java API
- 应用程序可通过这套API连接到关系数据库完成对数据库中数据的査询、更新和删除等操作
2.JDBC与数据库驱动的关系
- Sun公司在JDBC中定义数据库操作的相关接口而各数据库厂商在其数据库驱动中实现了这些接口
- Sun公司并没有提供Java语言与各数据打交道的具体API;而是制定了相关的标准和规范;各数据库厂商(比如MySQL,Oracle,DB2等)在其数据库驱动中实现了这些接口(规范)。
- JDBC屏蔽了Java与不同数据库打交道的细节问题
二.JDBC操作步骤
1.添加jar包
- 添加MySQL所需jar包,如:mysql-connector-java-5.1.7-bin.jar 到 Java项目lib文件夹中并执行Build Path
(1)eclipse
(2)idea
2.加载驱动
(1)加载方式1
- 利用java.sql.DriverManager.registerDriver( )方法加载驱动
- 该方式不但强烈依赖数据库的驱动jar而且会导致驱动被重复注册2次
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
(2)加载方式2(推荐)
Class.forName(“com.mysql.jdbc.Driver”);
3.创建链接
- java.sql.Drivermanager类中的getConnection()方法与数据库建立连接。
(1)语法
DriverManager.getConnection(“jdbc:mysql://数据库地址:端口号/数据库名”,”用户名”, “密码”);
(2)示例
Connection connection = DriverManager.getConnection(“jdbc:mysql:
- jdbc: 表示协议
- mysql: 表示子协议
- localhost: 代表数据库地址
- 3306: 表示端口号: 表示要连接的数据库
- root: 表示用户名
- test: 表示密码
- java.sql.Connection:接口,用于与数据库交互;各数据库驱动中均实现了该接口
4.创建Statement对象
- 利用java.sql.Connection创建用于执行SQL语句的Statement
(1)使用
Statement statement = connection.createStatement();
- java.sql.Statement:接口用于操作SQL语句并返回相应的结果集;各数据库驱动中均实现了该接口
5.执行SQL语句
- 利用java.sql.Statement执行SQL语句
(1)常用方法
方法 | 方法描述 |
---|
execute(String sql ) | 该方法可以执行任意SQL语句。当且仅当执行select语句且有返回结果时该方法返回true, 其他情况下该方法返回false |
executeUpdate(String sql ) | 该方法常用于执行DML( INSERT、UPDATE或DELETE)和DDL语句。执行DML语句时返回受SQL语句影响的行数,执行DDL语句时返回0 |
executeQuery( String sql) | 该方法通常执行査询语句,执行后返回代表结果集的ResultSet对象 |
| |
(2)示例
ResultSet resultSet = statement.executeQuery(sql);
- statement.executeQuery( )方法:返回的是实现java.sql.ResultSet接口的对象
6.获得结果集
- 利用利用java.sql.Statement接口方法
(1)示例
ResultSet resultSet = statement.executeQuery(sql);
- java.sql.ResultSet:用于保存执行SQL语句之后得到的结果集;各数据库驱动中均实现了该接口。
- ResultSet:对外暴露一个游标,该游标默认指向结果集第一行之前。
(2)ResultSet常用方法
方法 | 方法描述 |
---|
boolean next() | 将游标从当前位置向下移动一行 |
boolean previous() | 将游标从当前位置向上移动一行 |
void afterLast() | 将光标移动到末尾,正好位于最后一行之后 |
void beforeFirst() | 将光标移动到开头,正好位于第一行之前 |
Object getObject(int columnIndex) | 根据序号取值,索引从1开始 |
Object getObject(String ColomnName) | 根据列名取值 |
int getInt(int colIndex) | 以int形式获取ResultSet结果集当前行指定列号值 |
int getInt(String colLabel) | 以int形式获取ResultSet结果集当前行指定列名值 |
float getFloat(int colIndex) | 以float形式获取ResultSet结果集当前行指定列号值 |
float getFloat(String colLabel) | 以float形式获取ResultSet结果集当前行指定列名值 |
String getString(int colIndex) | 以String形式获取ResultSet结果集当前行指定列号值 |
String getString(String colLabel) | 以String形式获取ResultSet结果集当前行指定列名值 |
Date getDate(int columnIndex) | 以Date形式获取ResultSet结果集当前行指定列号值 |
Date getDate(String columnName) | 以Date形式获取ResultSet结果集当前行指定列号值 |
void close() | 关闭ResultSet对象 |
7.处理结果
- 从ResultSet中获取到数据库中数据后,我们就将这些数据封装到JavaBean中
- 注意Java的数据类型与数据库的数据类型的对应关系
Java数据类型 | 数据库的数据类型 |
---|
byte | tityint |
int | int |
short | smallint |
long | bigint |
float | float |
double | double |
String | char/varchar |
Date | date |
8.关闭资源
- 数据库资源非常宝贵,数据库允许的并发访问连接数量有限。
- 当数据库资源用完后切记释放资源。
- 为了保证资源的释放,常在finally代码块中关闭与数据库操作相关的资源。
三.JDBC示例
1.建表
-- 若存在数据库test则删除
DROP DATABASE IF EXISTS test;
-- 创建数据库test
CREATE DATABASE test;
-- 选择数据库test
USE test;
-- 创建学生表
CREATE TABLE student (
studentid INT,
studentname VARCHAR(50)
);
-- 向学生表插入数据
INSERT INTO student (studentid,studentname) VALUES (1,"lili");
INSERT INTO student (studentid,studentname) VALUES (2,"dodo");
INSERT INTO student (studentid,studentname) VALUES (3,"tutu");
INSERT INTO student (studentid,studentname) VALUES (4,"mqmq");
INSERT INTO student (studentid,studentname) VALUES (5,"pmpm");
2.编写Javabean(实体类)
package cn.com.demo1;
public class Student {
private int studentID;
private String studentName;
public Student() {
}
public Student(int studentID, String studentName) {
this.studentID = studentID;
this.studentName = studentName;
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
@Override
public String toString() {
return "Student [studentID=" + studentID + ", studentName=" + studentName + "]";
}
}
3.使用JDBC操作数据库
package cn.com.demo1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//建立连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
//创建Statement
statement = connection.createStatement();
String sql = "select * from student";
//执行SQL
resultSet = statement.executeQuery(sql);
//处理结果
while (resultSet.next()) {
Student student = new Student();
int id = resultSet.getInt("studentid");
String name = resultSet.getString("studentname");
student.setStudentID(id);
student.setStudentName(name);
System.out.println(student);
}
} catch (Exception e) {
e.printStackTrace();
//关闭资源
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
resultSet = null;
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
}
SQL注入
1.SQL注入示例
(1)依据姓名查询学生信息
package cn.com.demo2;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//建立连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
//创建Statement
statement = connection.createStatement();
//依据姓名查找学生信息
String studentname="lili";
String sql = "select * from student where studentname="+"'"+studentname+"'";
System.out.println(sql);
//执行SQL
resultSet = statement.executeQuery(sql);
//处理结果
while (resultSet.next()) {
Student student = new Student();
int id = resultSet.getInt("studentid");
String name = resultSet.getString("studentname");
student.setStudentID(id);
student.setStudentName(name);
System.out.println(student);
}
} catch (Exception e) {
e.printStackTrace();
//关闭资源
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
resultSet = null;
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
}
(2)修改studentname的值
String studentname="abc' or '1=1";
- 没有传入正确的学生姓名居然查询出来所有学生的信息
- 我们使用Statement来执行SQL语句,在该过程中遭受到了SQL注入攻击。为了防止该类问题的发生,推荐使用PreparedStatement替代Statement。
- PreparedStatement是Statement的子类,它可防止SQL注入攻
preparedStatement
1.PreparedStatement概述
- PreparedStatement是Statement的子接口,它可以预编译 SQL 语句并将预编译后的SQL语句存储在PreparedStatement对象中
- 由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement对象
2.PreparedStatement使用步骤
- 编写带有?占位符的SQL语句
- 使用Connection的prepareStatement( )方法和包含了?占位符的SQL字符串创建PreparedStatement对象并对SQL语句进行预编译
- 使用PreparedStatement的setXXX(index , value)方法传入实参取代之前的?占位符
- 使用PreparedStatement的execute( )、 executeUpdate( ) 、 executeQuery( )方法执行 SQL 语句
3.PreparedStatement示例
package cn.com.demo3;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestJDBC {
public static void main(String[] args) {
TestJDBC jdbcDemo=new TestJDBC();
jdbcDemo.addStudent();
jdbcDemo.deleteStudent();
jdbcDemo.updateStudent();
jdbcDemo.findStudent();
}
//添加学生
private void addStudent() {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//建立连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
Student student=new Student(6, "zczc");
String sql = "insert into student values (?,?)";
//创建PrepareStatement
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, student.getStudentID());
preparedStatement.setString(2, student.getStudentName());
//执行SQL
preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
//关闭资源
} finally {
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
preparedStatement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
//删除学生
public void deleteStudent() {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//建立连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
String studentname="zczc";
String sql = "delete from student where studentname=?";
//创建PrepareStatement
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, studentname);
//执行SQL
preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
//关闭资源
} finally {
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
preparedStatement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
//修改学生
private void updateStudent() {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//建立连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
int studentid=1;
String studentname="hoho";
String sql = "update student set studentname=? where studentid=?";
//创建PrepareStatement
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, studentname);
preparedStatement.setInt(2, studentid);
//执行SQL
preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
//关闭资源
} finally {
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
preparedStatement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
//查找学生
private void findStudent() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//建立连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
//依据姓名查找学生信息
String studentname="lili";
String sql = "select * from student where studentname=?";
//创建PrepareStatement
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, studentname);
//执行SQL
resultSet = preparedStatement.executeQuery();
//处理结果
while (resultSet.next()) {
Student student = new Student();
int id = resultSet.getInt("studentid");
String name = resultSet.getString("studentname");
student.setStudentID(id);
student.setStudentName(name);
System.out.println(student);
}
} catch (Exception e) {
e.printStackTrace();
//关闭资源
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
resultSet = null;
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
preparedStatement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
}
atch (Exception e) {
e.printStackTrace();
//关闭资源
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
resultSet = null;
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
preparedStatement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
connection = null;
}
}
}
}