# 一、JDBC
## 1.1 JDBC概述
JDBC(Java Database Connectivity)Java数据库互联技术
JDBC技术是Java提供的用于操作关系型数据库的一套规范,这套规范提供了标准API用于操作实现了这套规范的数据库管理系统。

## 1.2 JDBC标准API
JDBC标签API基本都是在java.sql包下,其中最主要的几个接口:
| API | 用途 |
| :----------------------------: | :----------------------------------------------------------: |
| java.sql.DriverManager类 | 驱动管理器,用于构建数据库连接对象 |
| java.sql.Connection 接口 | 建立与数据库连接的抽象方法 |
| java.sql.Statement接口 | 用于与数据库进行SQL交互 |
| java.sql.PreparedStatement接口 | 是Statement接口的子接口,用于与数据库进行SQL交互,可以进预编译SQL语句 |
| java.sql.ResultSet接口 | 代表查询操作返回的结果集 |
## 1.3 JDBC操作MySQL数据库的步骤
### 1.3.1 导入数据库驱动并构建classpath路径
创建Java程序,在工程目录下创建lib目标,这个目录主要用于存放第三方Jar包,这个目标必须添加的类路径下,因为所有的类的字节码文件需要在类路径下才能被加载器加载到内存中,才能被程序使用。
###1.3.2 在程序中加载MySQL加驱动类
com.mysql.jdbc.Driver类就是MySQL核心驱动类
```java
Class.forName("com.mysql.jdbc.Driver");
```
### 1.3.3 建立数据库连接
使用JDBC提供的标准API : DriverManager驱动管理器类用于创建与数据库进行连接的对象
```java
Connection DriverManager.getConnection(url, username, password);
```
根据指定的数据库服务访问路径,用户名, 密码来获取一个实现了Connection接口的实现对象(不需要关注), 这个实现对象肯定实现了Connection接口中的所有抽象方法,所以Java程序只需要面向接口编程即可。
```java
url的格式 : jdbc:mysql://ip地址:端口号/数据库名称
```
private static String driverName = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql://localhost:3306/d_student";
private static String username = "root";
private static String password = "root";
public static void main(String[] args) {
try {
// 1.加载驱动类
Class.forName(driverName);
// 2.建立数据库连接 MySQL驱动实现Connection接口的实现类JDBC4Connection类
Connection connection = DriverManager.getConnection(url, username, password);
### 1.3.4 获取表达式对象
该对象是用于向数据库发送SQL指令,以及获取数据库返回的响应结果
```java
Statement 连接对象.createStatement();
这个Statement接口不建议使用,这个接口的方法在传递SQL语句是,数据以拼接方式拼接到SQL语句中,存在SQL注入问题,另外这个接口在发送SQL语句时,不会进行预编译,而是直接发送个MySQL服务进行解析和处理,影响MySQL数据的性能。
PreparedStatement对象 ,
连接对象.prepareStatement(String sql):在构造这个对象时需要传入SQL语句,内部会对SQL语句进行预编译,并且数据不是以拼接的方式组织到SQL语句中,而是使用占位符的方式内部进行替换;然后将编译后的SQL语句再发送给MySQL服务,MySQL服务只需要执行执行指令即可,性能会高些
```
常用的方法
executeUpdate():
```java
int executeUpdate(String sql) : 增、删、改的通用方法,返回值是受影响的函数
```
executeQuery():
```java
import java.sql.*;
/**
* ClassName: Demo01
* Package: com.dyh.demo
* Description:
*
* @Date: 2022/3/21 14:26
* @Author: tancheng
*/
public class Demo1 {
// 硬编码
private static String driverName = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql://localhost:3306/d_student";
private static String username = "root";
private static String password = "root";
public static void main(String[] args) {
try {
// 1.加载驱动类
Class.forName(driverName);
// 2.建立数据库连接 MySQL驱动实现Connection接口的实现类JDBC4Connection类
Connection connection = DriverManager.getConnection(url, username, password);
// 3.获取用于发送SQL语句和接收响应结果的接口
// 实际在使用不推荐使用Statement接口,而是使用其子接口
// PreparedStatement子接口
// Statement 增、删、改时,数据如果是不确定的,需要使用变量表示
// Statement发送的SQL语句需要拼接,Statement直接将拼接号的字符串
// 发送给MySQL服务器,由服务器解析,性能很差
// SQL注入问题:拼接带来的问题,查询时存在的问题
Statement statement = connection.createStatement();
// 4.调用statement对象的方法来进行增、删、改 executeUpdate()
// 这个方法的返回值是受影响的行数(int)
// 演示添加功能
// String sname = "测试11";
// int age = 22;
// String mobile = "9999";
// String addr = "测试地址22";
// String gender = "女";
//
// int row = statement.executeUpdate("insert into " +
// "student(stu_name, stu_age, stu_mobile, stu_addr, stu_gender) " +
// "values ('"+sname+"', "+age+", '"+mobile+"', '"+addr+"', '"+gender+"')");
// System.out.println(row);
// 演示修改功能
// int row = statement.executeUpdate("update student set stu_age=30, stu_mobile='11111', stu_addr='测试地址2' where stu_id=18");
// 演示删除功能
// int row = statement.executeUpdate("delete from student where stu_id=18");
// if(row > 0) {
// System.out.println("删除成功");
// } else {
// System.out.println("删除失败");
// }
// 演示查询功能
// ResultSet resultSet = statement.executeQuery("select * from student");
// // ResultSet接口
// while(resultSet.next()) { // 如果true,取出当前行的数据
// // 获取当前行的指定下标的字段中的数据,下标从1开始
// // 可以通过字段名称来获取指定列的数据
// int stuId = resultSet.getInt("stu_id");
// String stuName = resultSet.getString("stu_name");
// System.out.println("学号:" + stuId + " 姓名:" + stuName);
//
// }
String name = "张三' or '1'='1";
String mobile = "";
ResultSet resultSet = statement.executeQuery("select count(*) from student where stu_name='"+name+"' and stu_mobile='"+mobile+"' ");
if(resultSet.next()) {
int count = resultSet.getInt(1);
if(count == 1) {
System.out.println("登录成功!");
} else {
System.out.println("您输入的用户名或密码错误!");
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
ResultSet executeQuery(String sql) : 查询方法,返回值是ResultSet接口的实现对象,这个对象代表了查询的结果集
```
import java.sql.*;
/**
* ClassName: Demo2
* Package: com.dyh.demo
* Description:
*
* @Date: 2022/3/21 15:54
* @Author: tancheng
*/
public class Demo2 {
private static String driverName = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql://localhost:3306/d_student";
private static String username = "root";
private static String password = "root";
public static void main(String[] args) {
try {
// 1.加载驱动类
Class.forName(driverName);
// 2.建立数据库连接 MySQL驱动实现Connection接口的实现类JDBC4Connection类
Connection connection = DriverManager.getConnection(url, username, password);
// 3.获取PreparedStatement对象
PreparedStatement ps =
connection.prepareStatement("select count(*) from student where stu_name=? and stu_mobile=?");
// 4.设置参数,内部会自动判断类型,设置占位符的索引从1开始
String sname = "张三' or '1'='1";
String mobile = "66566";
ps.setObject(1, sname);
ps.setObject(2, mobile);
// 5.执行查询
ResultSet resultSet = ps.executeQuery();
if(resultSet.next()) {
int count = resultSet.getInt(1);
if(count == 1) {
System.out.println("登录成功!");
} else {
System.out.println("您输入的用户名或密码错误!");
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
}
}
}
这个ResultSet接口有一些对结果集进行操作的方法
```java
boolean next()方法 判断是否能遍历到下一行记录,如果能返回true,否则返回false
Xxx getXxx(索引|列名): 可以获取当前行指定索引或列表的数据
Xxx是Java的数据类型
Java的数据类型需要和MySQL数据库中的类型对应
String varchar char
int int
double double
Date date
```