Java - JDBC
文章目录
- Java - JDBC
- 引言
- JDBC
- 1 什么是JDBC
- 2 MySQL数据库驱动
- 3 JDBC开发步骤
- 4 具体介绍
引言
思考:
当下我们如何操作数据库?
- 使用客户端工具访问数据库,手工建立连接,输入用户名和密码登录。
- 编写SQL语句,点击执行,查看操作结果(结果集或受影响行数)。
实际开发中,会采用上述方式吗?
- 不会,因为操作量过大,无法保证效率和正确性。
- 普通用户不能直接操作客户端工具。
JDBC
1 什么是JDBC
概念:
- JDBC(Java DataBase Connectivity)Java数据库连接,SUN公司定义的一套连接数据库的规范(标准)。
- 使用JDBC连接数据库完成CRUD操作。
核心思想:
- JDBC中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。
- 由数据库厂商提供驱动实现类(Driver数据库驱动)。
如图:
2 MySQL数据库驱动
MySQL数据库驱动包:
- mysql-connector-java-5.1.X 适用于5.X版本。
- mysql-connector-java-8.0.X 适用于8.X版本。
JDBC API:
类型 | 全限定名 | 简介 |
---|---|---|
class | java.sql.DriverManager | 管理多个数据库驱动类,提供了获取数据库连接的方法。 |
interface | java.sql.Connection | 代表一个数据库连接。当connection不是null时,表示已连接数据库。 |
interface | java.sql.Statement | 发送SQL语句到数据库工具。 |
interface | java.sql.ResultSet | 保存SQL查询语句的结果数据(结果集)。 |
class | java.sql.SQLException | 处理数据库应用程序时所发生的异常。 |
3 JDBC开发步骤
开发六步骤:
-
注册驱动:
-
Class.forName("com.mysql.jdbc.Driver");
-
获取连接:
-
Connection conn = DriverManager.getConnection(url,name,pwd);
-
创建命令对象:
-
Statement statement = conn.createStatement();
-
执行SQL语句:
-
int result = statement.executeUpdate(sql);
-
处理结果:
-
System.out.println(result);
-
释放资源:
-
statement.close(); conn.close();
4 具体介绍
1 DriverManager类
概念:
- java.sql.DriverManager管理所有数据库的驱动,如果想要建立数据库连接需要先在java.sql.DriverManager中注册对应的驱动类,然后调用getConnection方法才能连接上数据库。
注册驱动:
-
方法1:(推荐使用)
-
Class.forName("com.mysql.jdbc.Driver");
-
方法2:(不推荐使用)
-
DriverManager.registerDriver(new Driver());
-
原因: 会导致注册两次, 耦合性高;
获取连接:
String url= "jdbc:mysql://localhost:3306/mysql";//连接字符串
String user= "root";//用户名
String password = "root";//密码
//jdbc:mysql 协议
//localhost 主机名
//3306 端口号
//mysql 数据库名
Connection connection = DriverManager.getConnection(url, user, password);
这样连接后会出现一个警告:
Fri Jan 26 09:35:24 CST 2024 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
这段警告信息是关于MySQL数据库SSL连接的,其翻译如下:
警告:在未验证服务器身份的情况下建立SSL连接是不推荐的。根据MySQL 5.5.45+、5.6.26+ 和 5.7.6+ 的要求,如果未设置明确选项,则必须默认建立SSL连接。为了兼容不使用SSL的现有应用程序,已将verifyServerCertificate属性设置为’false’。您需要明确通过设置useSSL=false来禁用SSL,或者设置useSSL=true并为服务器证书验证提供truststore。
简单来说,这个警告告诉你,你的MySQL连接没有使用SSL或者没有正确地验证服务器的SSL证书。为了安全起见,你应该考虑启用SSL并提供正确的证书验证,或者如果你确定不需要SSL,你可以明确禁用它。
怎么解决这个问题:
我们采用明确禁止SSL的方式:
更新 url (添加参数):
参数: ?useSSL=false&characterEncoding=utf-8
useSSL=false 明确禁止SSL
characterEncoding=utf-8 设置数据库编码为 UTF-8
url="jdbc:mysql://localhost:3306/mysql?useSSL=false&characterEncoding=utf-8";
2 Connection
概念:
- Connection接口代表与特定的数据库的连接,要对数据表中的数据进行操作,首先要获取数据库连接,Connection实现就像在应用程序中与数据库之间开通了一条渠道。
方法名 | 说明 |
---|---|
createStatement() | 创建Statement命令对象 |
prepareStatement(String sql) | 创建预编译命令对象 |
3 Statement
概念:
- 获取连接对象后,可以创建Statement对象,用来执行命令。
语法: Statement stat=连接对象.createStatement();
方法名 | 说明 |
---|---|
execute() | 执行任何SQL语句,一般不用 |
executeUpdate() | 执行增删改、创建库、表等 |
executeQuery() | 执行查询,返回ResultSet结果集 |
4 ResultSet
概念:
- 在执行查询SQL后,存放查询到的结果集数据。
接收结果集:
- ResultSet rs = statement.executeQuery(sql);
注意:
- 作用是完成了查询结果的存储功能,默认只能向前读取,不能修改.
遍历ResultSet结果集
- ResultSet以表结构进行临时结果的存储,通过JDBC API将其中数据进行依次获取
方法名 | 返回值类型 | 描述 |
---|---|---|
next(); | boolean | 数据行指针,每调用一次,指针向下移动一行。结果为 true,表示当前行有数据。结果为false,没有数据。 |
getXxx(编号); | xxx | 代表根据列的编号顺序获得,从 1 开始。 |
getXxx(“列名”); | xxx | 代表根据列名获得。推荐 |
**经验:**getXxx方法可以获取的类型有:基本数据类型、引用数据类型
5 常见错误
6 代码演示
代码演示-1
JDBCDemo1:
public class JDBCDemo1 {
public static void main(String[] args) throws Exception{
//1 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2 获取连接
//url: 连接字符串 jdbc:mysql://localhost:3306/companydb
//useSSL=false 明确禁用SSL
//characterEncoding=utf-8 设置字符编码为utf-8
//user: 用户名
//password: 密码
// 定义数据库连接参数
String url = "jdbc:mysql://localhost:3306/companydb?useSSL=false&characterEncoding=utf-8";
String username = "root";
String password = "root";
Connection connection = null;
connection = DriverManager.getConnection(url, username, password);
if (connection != null) {
System.out.println("连接成功...");
}
//3 关闭
// 关闭数据库连接
if (connection != null) {
connection.close();
}
}
}
代码演示-2
JDBCDemo2:
public class JDBCDemo2 {
public static void main(String[] args) throws Exception{
// 1 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 获取连接对象
// 定义数据库连接参数
String url = "jdbc:mysql://localhost:3306/companydb?useSSL=false&characterEncoding=utf-8";
String username = "root";
String password = "root";
Connection connection;
connection = DriverManager.getConnection(url, username, password);
// 3 创建命令对象
Statement statement = connection.createStatement();
// 4 执行命令
// 4.1 创建数据库
int count1 = statement.executeUpdate("create database if not exists myschool;");
// 4.2 切换数据库
int count2 = statement.executeUpdate("use myschool;");
// 4.3 创建数据表
int count3 = statement.executeUpdate("create table if not exists student(stu_id int primary key auto_increment, stu_name varchar(20), stu_age int);");
// 4.4 添加数据
int count4 = statement.executeUpdate("insert into student values (null,'张三',18),(null,'李四',19),(null,'王五',20);");
// 4.5 修改数据
int count5 = statement.executeUpdate("update student set stu_age = stu_age+5,stu_name='张利' where stu_id=1;");
// 4.6 删除数据
int count6 = statement.executeUpdate("delete from student where stu_id=1;");
// 4.7 删除数据表/数据库
// statement.executeUpdate("drop table student;");
// statement.executeUpdate("drop database myschool;");
// 5 处理
System.out.println("count1: "+ count1);
System.out.println("count2: "+ count2);
System.out.println("count3: "+ count3);
System.out.println("count4: "+ count4);
System.out.println("count5: "+ count5);
System.out.println("count6: "+ count6);
// 6 关闭资源
statement.close();
connection.close();
}
}
代码演示-3
JDBCDemo3:
public class JDBCDemo3 {
public static void main(String[] args) throws Exception{
// 1 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 定义数据库连接参数
String url = "jdbc:mysql://localhost:3306/companydb?useSSL=false&characterEncoding=utf-8";
String username = "root";
String password = "root";
// 2 获取连接对象
Connection connection;
connection = DriverManager.getConnection(url, username, password);
// 3 创建命令对象
Statement statement = connection.createStatement();
// 4 执行命令
ResultSet resultSet = statement.executeQuery("select * from student;");
// 5 处理
while (resultSet.next()) {
int stuId = resultSet.getInt("stu_id");
String stuName = resultSet.getString("stu_name");
int stuAge = resultSet.getInt("stu_age");
String stuGender = resultSet.getString("stu_gender");
String stuAddress = resultSet.getString("stu_address");
Date stuBorn = resultSet.getDate("stu_born");
System.out.println(stuId+"\t"+stuName+"\t"+stuAge+"\t"+stuGender+"\t"+stuAddress+"\t"+stuBorn);
}
// 6 关闭
resultSet.close();
statement.close();
connection.close();
}
}
代码演示-4
JDBCDemo4:
需求:
创建用户表(user): 字段:user_id,user_name,password,age,phone,email
实现用户登录功能
public class JDBCDemo4 {
public static void main(String[] args) throws Exception{
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名");
//回车返回
String user_name = scanner.nextLine();
System.out.println("请输入密码");
//空格返回
String user_pwd = scanner.next();
// 1 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 定义数据库连接参数
String url = "jdbc:mysql://localhost:3306/companydb?useSSL=false&characterEncoding=utf-8";
String username = "root";
String password = "root";
// 2 获取连接对象
Connection connection;
connection = DriverManager.getConnection(url, username, password);
// 3 创建命令对象
//当在 SQL 中使用字符串时,必须非常小心,确保采取适当的安全措施,以防止 SQL 注入和其他安全威胁。
String sql = "select * from user where user_name = '" + user_name + "' and password = '" + user_pwd + "'";
Statement statement = connection.createStatement();
// 4 执行命令
//容易受到 SQL 注入攻击
ResultSet resultSet = statement.executeQuery(sql);
// 5 处理
if (resultSet.next()) {
System.out.println("登录成功...");
} else {
System.out.println("登录失败...");
}
// 6 关闭
resultSet.close();
statement.close();
connection.close();
}
}
SQL注入攻击:
请输入用户名
xxxx' or 1=1;#
请输入密码
root
登录成功...
什么是SQL注入攻击?
SQL注入:用户输入的数据中有SQL关键字或语句并且参与了SQL语句的编译,导致SQL语句编译后的条件含义为true,实现欺骗服务器,一直得到正确的结果。这种现象称为SQL注入。
如何避免:
不要使用SQL拼接方式,SQL 语句要在用户输入数据前就已编译成完整的 SQL 语句,再进行填充数据。
PreparedStatement
概念:
- PreparedStatement继承了Statement接口,执行SQL语句的方法无异。
作用:
- 预编译SQL语句,效率高。
- 安全,避免SQL注入。
- 可以动态的填充数据,执行多次同构的SQL语句。
应用:
-
预编译SQL语句,数据参数使用?占位:
-
PreparedStatement pstmt = null; pstmt = conn.prepareStatement("select * from user where uname=? and pwd=?");
-
为参数下标赋值:
-
pstmt.setString(1,”Gavin”); pstmt.setString(2,”123456”);
注意:
- JDBC中的所有参数都由 ?符号占位,这被称为参数占位符。
- 在执行SQL语句之前,必须为每个参数提供值。
- 当你不知道数据参数的类型是什么时, 可以使用
setObject();
方法
预编译命令, 预防SQL注入攻击
请输入用户名
xxxx' or 1=1;#
请输入密码
root
登录失败...