JDBC编程六步
JDBC编程的步骤是很固定的,通常包含以下六步:
- 第一步:注册驱动
- 作用一:将 JDBC 驱动程序从硬盘上的文件系统中加载到内存中。
- 作用二:使得 DriverManager 可以通过一个统一的接口来管理该驱动程序的所有连接操作。
- 第二步:获取数据库连接
- 获取java.sql.Connection对象,该对象的创建标志着mysql进程和jvm进程之间的通道打开了。
- 第三步:获取数据库操作对象
- 获取java.sql.Statement对象,该对象负责将SQL语句发送给数据库,数据库负责执行该SQL语句。
- 第四步:执行SQL语句
- 执行具体的SQL语句,例如:insert delete update select等。
- 第五步:处理查询结果集
- 如果之前的操作是DQL查询语句,才会有处理查询结果集这一步。
- 执行DQL语句通常会返回查询结果集对象:java.sql.ResultSet。
- 对于ResultSet查询结果集来说,通常的操作是针对查询结果集进行结果集的遍历。
- 第六步:释放资源
- 释放资源可以避免资源的浪费。在 JDBC 编程中,每次使用完 Connection、Statement、ResultSet 等资源后,都需要显式地调用对应的 close() 方法来释放资源,避免资源的浪费。
- 释放资源可以避免出现内存泄露问题。在 Java 中,当一个对象不再被引用时,会被 JVM 的垃圾回收机制进行回收。但是在 JDBC 编程中,如果不显式地释放资源,那么这些资源就不会被 JVM 的垃圾回收机制自动回收,从而导致内存泄露问题。
JDBC完成新增操作
新增操作就是让数据库执行insert语句。通过这个操作来学习一下JDBC编程的每一步。刚开始编写JDBC代码的时候,建议使用文本编辑器,先不借助任何IDE。
JDBC编程第一步:注册驱动
注册驱动有两个作用:
- 将 JDBC 驱动程序从硬盘上的文件系统中加载到内存。
- 让 DriverManager 可以通过一个统一的接口来管理该驱动程序的所有连接操作。
JDK的API帮助文档:
代码如下:
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JDBCTest01 {
public static void main(String[] args){
try {
// 1. 注册驱动
// com.mysql.cj.jdbc.Driver 是MySQL驱动最核心的类,
// 这个类实现了 java.sql.Driver 接口
Driver driver = new com.mysql.cj.jdbc.Driver(); // 创建MySQL驱动对象
DriverManager.registerDriver(driver); // 完成驱动注册
} catch(SQLException e){
e.printStackTrace();
}
}
}
注意:注册驱动调用的是java.sql.DriverManager的静态registerDriver()方法。这些方法的使用要参阅JDK的API帮助文档。
思考1:为什么以上代码中new的时候,后面类名要带上包名呢?
因为这个Driver和java.sql.Driver的Driver不是同一个包的
思考2:以上代码中哪些是JDBC接口,哪些是JDBC接口的实现?
new com.mysql.cj.jdbc.Driver();这个是MySQL对java制定的driver规则的实现
JDBC编程第二步:获取连接
获取java.sql.Connection对象,该对象的创建标志着mysql进程和jvm进程之间的通道打开了。
代码实现
API帮助文档:
代码如下:
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
public class JDBCTest01 {
public static void main(String[] args){
try {
// 1. 注册驱动
Driver driver = new com.mysql.cj.jdbc.Driver(); // 创建MySQL驱动对象
DriverManager.registerDriver(driver); // 完成驱动注册
// 2. 获取连接
String url = "jdbc:mysql://localhost:3306/jdbc";
String user = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println("连接对象:" + conn);
} catch(SQLException e){
e.printStackTrace();
}
}
}
执行结果如下:
看到以上的输出结果,表示数据库已经连接成功了。
通过以上程序的输出结果得知:com.mysql.cj.jdbc.ConnectionImpl是java.sql.Connection接口的实现类,大家可以想象一下,如果换成Oracle数据库的话,这个实现类的类名是不是就会换一个呢?答案是肯定的。不过对于我们来说是不需要关心具体实现类的,因为后续的代码都是直接面向java.sql.Connection接口来调用方法的。面向接口编程在这里体现的淋漓尽致。确实降低了耦合度。
JDBC编程第三步:获取数据库操作对象
数据库操作对象是这个接口:java.sql.Statement。这个对象负责将SQL语句发送给数据库服务器,服务器接收到SQL后进行编译,然后执行SQL。
API帮助文档如下:
获取数据库操作对象代码如下:
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
public class JDBCTest01 {
public static void main(String[] args){
try {
// 1. 注册驱动
Driver driver = new com.mysql.cj.jdbc.Driver(); // 创建MySQL驱动对象
DriverManager.registerDriver(driver); // 完成驱动注册
// 2. 获取连接
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf-8";
String user = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, user, password);
// 3. 获取数据库操作对象
Statement stmt = conn.createStatement();
System.out.println("数据库操作对象stmt = " + stmt);
} catch(SQLException e){
e.printStackTrace();
}
}
}
执行结果如下:
同样可以看到:java.sql.Statement接口在MySQL驱动中的实现类是:com.mysql.cj.jdbc.StatementImpl。不过我们同样是不需要关心这个具体的实现类。因为后续的代码仍然是面向Statement接口写代码的。
另外,要知道的是通过一个Connection对象是可以创建多个Statement对象的:
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
public class JDBCTest01 {
public static void main(String[] args){
try {
// 1. 注册驱动
Driver driver = new com.mysql.cj.jdbc.Driver(); // 创建MySQL驱动对象
DriverManager.registerDriver(driver); // 完成驱动注册
// 2. 获取连接
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf-8";
String user = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, user, password);
// 3. 获取数据库操作对象
Statement stmt = conn.createStatement();
System.out.println("数据库操作对象stmt = " + stmt);
Statement stmt2 = conn.createStatement();
System.out.println("数据库操作对象stmt2 = " + stmt2);
} catch(SQLException e){
e.printStackTrace();
}
}
}
执行结果:
JDBC编程第四步:执行SQL
当获取到Statement对象后,调用这个接口中的相关方法即可执行SQL语句。
API帮助文档如下:
该方法的参数是一个SQL语句,只要将insert语句传递过来即可。当执行executeUpdate(sql)方法时,JDBC会将sql语句发送给数据库服务器,数据库服务器对SQL语句进行编译,然后执行SQL。
该方法的返回值是int类型,返回值的含义是:影响了数据库表当中几条记录。例如:返回1表示1条数据插入成功,返回2表示2条数据插入成功,以此类推。如果一条也没有插入,则返回0。
该方法适合执行的SQL语句是DML,包括:insert delete update。
代码实现如下:
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
public class JDBCTest01 {
public static void main(String[] args){
try {
// 1. 注册驱动
Driver driver = new com.mysql.cj.jdbc.Driver(); // 创建MySQL驱动对象
DriverManager.registerDriver(driver); // 完成驱动注册
// 2. 获取连接
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf-8";
String user = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, user, password);
// 3. 获取数据库操作对象
Statement stmt = conn.createStatement();
// 4. 执行SQL语句
String sql = "insert into t_user(name,password,realname,gender,tel) values('tangsanzang','123','唐三藏','男','12566568956')"; // sql语句最后的分号';'可以不写。
int count = stmt.executeUpdate(sql);
System.out.println("插入了" + count + "条记录");
} catch(SQLException e){
e.printStackTrace();
}
}
}
执行结果如下:
数据库表变化了:
第五步去哪里了?第五步是处理查询结果集,以上操作不是select语句,所以第五步直接跳过,直接先看一下第六步释放资源。【后面学习查询语句的时候,再详细看第五步】
为什么要释放资源
在 JDBC 编程中,建立数据库连接、创建 Statement 对象等操作都需要申请系统资源,例如打开网络端口、申请内存等。为了避免占用过多的系统资源和避免出现内存泄漏等问题,我们需要在使用完资源后及时释放它们。
释放资源的原则
原则1:在finally语句块中释放
- 建议在finally语句块中释放,因为程序执行过程中如果出现了异常,finally语句块中的代码是一定会执行的。也就是说:我们需要保证程序在执行过程中,不管是否出现了异常,最后的关闭是一定要执行的。当然了,也可以使用Java7的新特性:Try-with-resources。Try-with-resources 是 Java 7 引入的新特性。它简化了资源管理的代码实现,可以自动释放资源,减少了代码出错的可能性,同时也可以提供更好的代码可读性和可维护性。
原则2:释放有顺序
- 从小到大依次释放,创建的时候,先创建Connection,再创建Statement。那么关闭的时候,先关闭Statement,再关闭Connection。
原则3:分别进行try…catch…
- 关闭的时候调用close()方法,该方法有异常需要处理,建议分别对齐try…catch…进行异常捕获。如果只编写一个try…catch…进行一块捕获,在关闭过程中,如果某个关闭失败,会影响下一个资源的关闭。
代码如何实现
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
public class JDBCTest01 {
public static void main(String[] args){
Connection conn = null;
Statement stmt = null;
try {
// 1. 注册驱动
Driver driver = new com.mysql.cj.jdbc.Driver(); // 创建MySQL驱动对象
DriverManager.registerDriver(driver); // 完成驱动注册
// 2. 获取连接
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf-8";
String user = "root";
String password = "123456";
conn = DriverManager.getConnection(url, user, password);
// 3. 获取数据库操作对象
stmt = conn.createStatement();
// 4. 执行SQL语句
String sql = "insert into t_user(name,password,realname,gender,tel) values('tangsanzang','123','唐三藏','男','12566568956')"; // sql语句最后的分号';'可以不写。
int count = stmt.executeUpdate(sql);
System.out.println("插入了" + count + "条记录");
} catch(SQLException e){
e.printStackTrace();
} finally {
// 6. 释放资源
if(stmt != null){
try{
stmt.close();
}catch(SQLException e){
e.printStackTrace();
}
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
}
}
}
}