JDBC 编程的原理与使用
大家好,已经好久没更新了 , 学校的学业有点忙 , 没有额外的精力去进行更新了 , 假期开始了 , 我们也要开始努力了
数据库相对来说难度不是那么高,大家只要勤加练习、熟记语法,我相信学好数据库不是什么问题,博主会从0剖析,逐步讲解数据库的知识点,并且会举很多实例。最重要的是,博主不会采用软件,使用最原始的方式 -> 命令行来讲解,这样讲解的好处是逐个语句进行书写,不会造成读者思路跟不上的问题!
一. JDBC 的工作原理
1.1 工作原理
MySQL 是一个客户端-服务器结构的程序 , 但是并不是所有的数据库是这样的 . Oracle / SQL Server也是客户端 - 服务器结构的 , 但是 SQLite 就不是
咱们通过代码实现的操作数据库的程序 , 本质上也是一个MySQL 客户端 , 但是咱们不能手动实现 MySQL 服务器 , 因为实在是太复杂了
像主流的数据库 , 都会提供一些 API 接口 , 方便程序员自己 DIY 数据库客户端 , 这就称为 “数据库SDK”
API : 提供了一些 函数/方法/类 , 可以让程序员直接调用来完成一些功能 , 比如我们之前学过的 Java 标准库里面提供的类 , 也可以叫做 " Java API "
SDK : 范围更大 , 在提供 API 的基础上 , 还会提供一些可执行程序(工具) 辅助开发或者调试
那么 API 是数据库提供的 , 那有可能不同厂商推出的 API 完全不同 , 这就增加了大家的学习成本 , 但是这个标准还不好让自己人设定 , 所以 Java 提供了一套标准的接口体系 , 我们只需要学习 Java 官方提供给我们的这套体系即可 , 数据库公司会尽量让他们的 API 贴近于官方体系 , 那么 Java 提供的这套操作数据库的 API 就叫做 JDBC .
那么每个厂商为了贴近这套官方体系 , 还可能需要额外的程序帮助完成工作 , 那么这个东西就叫做 " JDBC 驱动包".
1.2 JDBC驱动包的下载
JDBC 驱动包哪里获取呢 ?
可以去我们的 Maven 中央仓库
搜索 MySQL
点进去之后 , 选择版本 , 因为我们的 MySQL 就是 5.x 版本 , 所以我们的驱动包也要下载 5.x 系列的 ,一定要确保大版本在 5 ,小版本无所谓
点击 jar 进行下载
下载成功后 , 我们来看一下 jar 包 , 我们就可以把它理解为是一个压缩包 , 里面存储的都是 .class 文件 , 我们可以用解压缩软件查看
我随便点进去的某一个文件夹
1.3 JDBC驱动包的导入
下载好 JDBC 驱动包之后 , 我们创建项目
点击项目名 , 右键 , New , Directory
起一个叫做 lib 的文件夹
然后找到我们下载的 JDBC 驱动包 , 拖进 lib 文件夹
右键 lib , 然后 Add as Library
最后 , 我们就导入成功了
二. JDBC的使用
在接下来的一系列操作之前 , 我们先做一些准备工作
创建一个数据库
create database test;
使用数据库
use test;
创建一个数据表
create table Test(id int,name varchar(20));
2.1 描述数据库的位置
我们要想操作数据库 , 就需要先连接上数据库的服务器 , 要想连接上服务器 , 就需要描述出服务器所在位置
在 JDBC 中 , 我们用 DataSource 来描述数据库的位置
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
public class JDBCTest {
public static void main(String[] args) {
DataSource dataSource = new MysqlDataSource();
}
}
所以我们采用向上转型的做法 , MysqlDataSource 实现了 DataSource , 这个了来自于驱动包 , 我们驱动包要是导入不成功 , 就不能成功使用
接下来我们具体指定数据库服务器位置
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
public class JDBCTest {
public static void main(String[] args) {
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl();//目前这句话有问题,括号里应该填写参数
}
}
((MysqlDataSource)dataSource).setUrl();
这句代码又实现了向下转型那有的同学问了 , 你转来转去的在干嘛 ?
那我们还有一种写法
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
public class JDBCTest {
public static void main(String[] args) {
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setUrl();//目前这句话有问题,括号里应该填写参数
}
}
但是不推荐第二种写法 , 因为第一种写法 , 我们的数据源是 DataSource 类型 , 后续写其他的代码 , 需要使用到数据源 , 那么它的类型是 DataSource 类型 , 他是通用类型 , 可以代表所有数据库 , 将来我们要换数据库了 , 只需要把实例化部分改成别的数据库即可 , 就不用改一大堆了
但是第二种写法 , 数据源是 MysqlDataSource 类型 , 后续其他位置需要数据源 , 对应的位置也都是 MySQL 数据库了 . 将来要是更换数据库 , 那么我们就需要把散落在各个位置的 MysqlDataSource 进行修改 , 十分麻烦 .
这其实就是多态的好处 , 我们之前学习 “封装” , 封装是为了程序员不必了解太多的实现细节 , 就可以直接使用 , 从而降低使用成本.
“多态” 就是在封装的基础上 , 程序员不需要关心实现的细节 , 甚至对象是什么类型都可以不用考虑了 , 更一步降低使用成本
那么接下来 , 我们继续完善代码 , 我们上面的setUrl()
里面还没填参数
那么实现一下
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
public class JDBCTest {
public static void main(String[] args) {
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
}
}
括号里面这么长一串 , 我们写一次就好 , 之后不断复制就可以了.
IP地址 端口号 数据库名我们已经描述完了 , 接下来要在描述一下用户名以及密码
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
public class JDBCTest {
public static void main(String[] args) {
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("haha");
}
}
2.2 建立数据库连接
网络通信中 , 有两种情况 :
- 有连接 : 相当于"打电话"
- 无连接 : 相当于"发微信"
数据库采用的就是有连接这种情况
使用 dataSource.getConnection
来建立连接
但是 getConnetion 报错了 , 这是因为数据库采用的是有连接的形式 , 在连接之前 , 会先投石问路 , 看链路是否通畅 , 然后最后也要及时释放资源 , 但是假如和数据库连接失败 , 就会抛出异常 . 所以我们要处理一下异常
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class JDBCTest {
public static void main(String[] args) throws SQLException {
//1.使用 DataSource 描述 MySQL 服务器的位置
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("baba");
//2.和数据库服务器建立连接
Connection connection = dataSource.getConnection();
}
}
我们再加一条语句 , 方便查看具体效果
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class JDBCTest {
public static void main(String[] args) throws SQLException {
//1.使用 DataSource 描述 MySQL 服务器的位置
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("baba");
//2.和数据库服务器建立连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
}
}
那么假如我们密码设置错误了
2.3 创建操作命令(Statement)
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JDBCTest {
public static void main(String[] args) throws SQLException {
//1.使用 DataSource 描述 MySQL 服务器的位置
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("haha");
//2.和数据库服务器建立连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
//3.构造 SQL 语句,JDBC操作数据库,本质上还是通过SQL来描述数据库操作
String sql = "insert into test values (1,'甄嬛')";
//不光构造出来还不行,需要搭配 PreparedStatement 类使用
PreparedStatement statement = connection.prepareStatement(sql);
}
}
2.4 执行SQL语句
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JDBCTest {
public static void main(String[] args) throws SQLException {
//1.使用 DataSource 描述 MySQL 服务器的位置
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("haha");
//2.和数据库服务器建立连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
//3.构造 SQL 语句,JDBC操作数据库,本质上还是通过SQL来描述数据库操作
String sql = "insert into test values (1,'甄嬛')";
//不光构造出来还不行,需要搭配 PreparedStatement 类使用
PreparedStatement statement = connection.prepareStatement(sql);
//4.执行 SQL 语句
//input update delete都是通过 executeUpdate 来执行的
//select 则是通过 executeQuery 来执行的
//返回值代表这个操作影响到几行
int n = statement.executeUpdate();
System.out.println(n);
}
}
2.5 释放资源
要注意的一点 : 后创建的先释放
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JDBCTest {
public static void main(String[] args) throws SQLException {
//1.使用 DataSource 描述 MySQL 服务器的位置
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("baba");
//2.和数据库服务器建立连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
//3.构造 SQL 语句,JDBC操作数据库,本质上还是通过SQL来描述数据库操作
String sql = "insert into test values (1,'甄嬛')";
//不光构造出来还不行,需要搭配 PreparedStatement 类使用
PreparedStatement statement = connection.prepareStatement(sql);
//4.执行 SQL 语句
//input update delete都是通过 executeUpdate 来执行的
//select 则是通过 executeQuery 来执行的
//返回值代表这个操作影响到几行
int n = statement.executeUpdate();
System.out.println(n);
//5.断开连接,释放资源
statement.close();
connection.close();
}
}
那么我们执行代码 , 看一下效果
2.6 用户输入信息构造 SQL
那么我们想要让用户输入要插入的内容呢 ?
那么上面这种情况就写死了
我们可以这样做
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
public class JDBCInsert {
public static void main(String[] args) throws SQLException {
//1.使用 DataSource 描述 MySQL 服务器的位置
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("baba");
//2.和数据库服务器建立连接
Connection connection = dataSource.getConnection();
//System.out.println(connection);
//3.让用户输入想要插入的数据
//next 读到空白符(空格, 制表符, 翻页符, 换行符, 回车符, 垂直制表符.....) 推荐
//nextLine 读到换行符
Scanner sc = new Scanner(System.in);
System.out.println("请输入要插入的同学学号:");
int id = sc.nextInt();
System.out.println("请输入要插入的同学的姓名:");
String name = sc.next();
//3.构造 SQL 语句,JDBC操作数据库,本质上还是通过SQL来描述数据库操作
String sql = "insert into test values (" + id + ",'" + name + "')";
//不光构造出来还不行,需要搭配 PreparedStatement 类使用
PreparedStatement statement = connection.prepareStatement(sql);
//4.执行 SQL 语句
//input update delete都是通过 executeUpdate 来执行的
//select 则是通过 executeQuery 来执行的
//返回值代表这个操作影响到几行
int n = statement.executeUpdate();
System.out.println(n);
//5.断开连接,释放资源
statement.close();
connection.close();
}
}
其实这个方法并不好 , 因为比如这句代码 , 看起来就很乱
String sql = "insert into test values (" + id + ",'" + name + "')";
而且这种情况并不是最糟糕的 , 有一种叫做 “SQL注入攻击” , 因为 name 是用户自己构造的 , 那么用户故意构造一组其他 SQL 呢 , 比如
name = ');drop table test;
那么我给大家讲解一下正确方式
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
public class JDBCInsert {
public static void main(String[] args) throws SQLException {
//1.使用 DataSource 描述 MySQL 服务器的位置
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("baba");
//2.和数据库服务器建立连接
Connection connection = dataSource.getConnection();
//System.out.println(connection);
//3.让用户输入想要插入的数据
//next 读到空白符(空格, 制表符, 翻页符, 换行符, 回车符, 垂直制表符.....) 推荐
//nextLine 读到换行符
Scanner sc = new Scanner(System.in);
System.out.println("请输入要插入的同学学号:");
int id = sc.nextInt();
System.out.println("请输入要插入的同学的姓名:");
String name = sc.next();
//3.构造 SQL 语句,JDBC操作数据库,本质上还是通过SQL来描述数据库操作
//使用 ? 作为占位符. 后续使用 statement 对象针对 ? 进行替换.
String sql = "insert into test values(?, ?)";
//不光构造出来还不行,需要搭配 PreparedStatement 类使用
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1,id);//括号里面前面代表第一个问号,后面代表修改成功需要的值
statement.setString(2,name);
//4.执行 SQL 语句
//input update delete都是通过 executeUpdate 来执行的
//select 则是通过 executeQuery 来执行的
//返回值代表这个操作影响到几行
int n = statement.executeUpdate();
System.out.println(n);
//5.断开连接,释放资源
statement.close();
connection.close();
}
}
我们来试一下
再去数据库查询一下