当前位置: 首页 > article >正文

JDBC编程六步详解:从注册驱动到释放资源

一、JDBC编程六步


JDBC编程的步骤是很固定的,通常包含以下六步:

第一步:注册驱动

(大白话:告诉java程序即将连接哪个品牌的数据库:MYsql或Oracle...)

  • 作用一:将 JDBC 驱动程序从硬盘上的文件系统中加载到内存中。
  • 作用二:使得 DriverManager 可以通过一个统一的接口来管理该驱动程序的所有连接操作。

第二步:获取数据库连接

获取 java.sql.Connection 对象,该对象的创建标志着 MySQL 进程和 JVM 进程之间的通道打开了。

第三步:获取数据库操作对象

获取 java.sql.Statement 对象,该对象负责将 SQL 语句发送给数据库,数据库负责执行该 SQL 语句。

第四步:执行 SQL 语句

执行具体的 SQL 语句,例如:insertdeleteupdateselect 等。

第五步:处理查询结果集

  • 如果之前的操作是 DQL 查询语句,才会有处理查询结果集这一步。
  • 执行 DQL 语句通常会返回查询结果集对象:java.sql.ResultSet
  • 对于 ResultSet 查询结果集来说,通常的操作是针对查询结果集进行结果集的遍历。

第六步:释放资源

  • 避免资源浪费:在 JDBC 编程中,每次使用完 ConnectionStatementResultSet 等资源后,都需要显式地调用对应的 close() 方法来释放资源,避免资源的浪费。
  • 避免内存泄露:在 Java 中,当一个对象不再被引用时,会被 JVM 的垃圾回收机制进行回收。但是在 JDBC 编程中,如果不显式地释放资源,那么这些资源就不会被 JVM 的垃圾回收机制自动回收,从而导致内存泄露问题。

二、 数据的准备

使用PowerDesigner设计用户表t_user。

使用Navicat for MySQL创建数据库,创建表,插入数据。

三、JDBC完成新增操作

新增操作就是让数据库执行insert语句。通过这个操作来学习一下JDBC编程的每一步。刚开始编写JDBC代码的时候,建议使用文本编辑器,先不借助任何IDE。

1.JDBC编程第一步:注册驱动

注册驱动有两个作用:


1.将 JDBC 驱动程序从硬盘上的文件系统中加载到内存。
2.让 DriverManager 可以通过一个统一的接口来管理该驱动程序的所有连接操作。

API帮助文档:

代码如下:

// 导入 java.sql.Driver 接口,该接口表示 JDBC 驱动程序,用于与数据库建立连接
import java.sql.Driver;
// 导入 java.sql.DriverManager 类,它是 JDBC 的管理层,负责管理 JDBC 驱动程序的注册和获取数据库连接
import java.sql.DriverManager;
// 导入 java.sql.SQLException 类,用于处理在使用 JDBC 进行数据库操作时可能出现的 SQL 异常
import java.sql.SQLException;

// 定义一个名为 JDBCTest01 的公共类,用于测试 JDBC 驱动程序的注册
public class JDBCTest01 {
    // 程序的入口点,Java 虚拟机从这里开始执行程序
    public static void main(String[] args) {
        // 使用 try-catch 块捕获可能在注册驱动过程中出现的 SQLException 异常
        try {
            // 1. 注册驱动
            // 创建一个 MySQL 驱动对象,com.mysql.cj.jdbc.Driver 是 MySQL 8.0 及以上版本的 JDBC 驱动类
            // 该类实现了 java.sql.Driver 接口,用于与 MySQL 数据库建立连接
            Driver driver = new com.mysql.cj.jdbc.Driver();
            // 调用 DriverManager 类的 registerDriver 方法,将创建的 MySQL 驱动对象注册到 DriverManager 中
            // 这样 DriverManager 就知道可以使用该驱动程序来建立与 MySQL 数据库的连接
            DriverManager.registerDriver(driver);
        } catch (SQLException e) {
            // 如果在注册驱动过程中出现 SQLException 异常,调用异常对象的 printStackTrace 方法
            // 该方法会将异常的堆栈跟踪信息输出到标准错误流,方便开发人员调试和定位问题
            e.printStackTrace();
        }
    }
}
  1. 导入必要的包

    • java.sql.Driver:表示 JDBC 驱动程序的接口,用于与数据库建立连接。
    • java.sql.DriverManager:负责管理 JDBC 驱动程序的注册和获取数据库连接。
    • java.sql.SQLException:用于处理在使用 JDBC 进行数据库操作时可能出现的 SQL 异常。
  2. 定义类和主方法

    • JDBCTest01 类是一个公共类,包含 main 方法,这是 Java 程序的入口点。
  3. 注册驱动程序

    • 创建 com.mysql.cj.jdbc.Driver 类的实例,该类是 MySQL 8.0 及以上版本的 JDBC 驱动类。
    • 调用 DriverManager.registerDriver(driver) 方法将驱动程序注册到 DriverManager 中。
  4. 异常处理

    • 使用 try-catch 块捕获可能在注册驱动过程中出现的 SQLException 异常。
    • 如果出现异常,调用 e.printStackTrace() 方法将异常的堆栈跟踪信息输出到标准错误流。

⑴.注意事项:

在实际开发中,通常不建议使用 DriverManager.registerDriver 方法来注册驱动程序,因为这种方式会导致驱动程序被注册两次。更推荐使用 Class.forName("com.mysql.cj.jdbc.Driver") 方法来加载驱动类,这种方式会利用 Java 的类加载机制自动完成驱动程序的注册


⑵.DriverManager.registerDriver

方法定义

DriverManager.registerDriver 方法定义在 java.sql.DriverManager 类中,用于向 DriverManager 注册一个 JDBC 驱动程序。其方法签名如下

public static synchronized void registerDriver(java.sql.Driver driver) 
throws SQLException

参数:driver 是一个实现了 java.sql.Driver 接口的对象,代表要注册的 JDBC 驱动程序。

异常:如果注册过程中出现问题,会抛出 SQLException 异常。

作用

DriverManager 是 JDBC 的管理层,负责管理 JDBC 驱动程序的注册和获取数据库连接。

registerDriver 方法的主要作用是将一个具体的 JDBC 驱动程序注册到 DriverManager 中,这样 DriverManager 就知道可以使用该驱动程序来建立与相应数据库的连接。

当调用 DriverManager.getConnection 方法时,DriverManager 会遍历已注册的驱动程序,找到合适的驱动来建立连接。

注意:注册驱动调用的是java.sql.DriverManager的registerDriver()方法。这些方法的使用要参阅JDK的API帮助文档。


⑶.思考1:为什么以上代码中new的时候,后面类名要带上包名呢?

①避免类名冲突

指定1包下的Driver类

Java 中可能存在多个类具有相同的简单类名,但位于不同的包中。如果只使用简单类名,编译器将无法确定具体要使用哪个类。

例如,在不同的包中可能有多个名为 Driver 的类。java.sql.Driver 是 JDBC 规范定义的一个接口,而 com.mysql.cj.jdbc.Driver 是 MySQL 数据库 JDBC 驱动实现这个接口的具体类。如果不指定完整的包名,编译器就不清楚你要创建的是哪个 Driver 类的实例。

import java.sql.Driver;

// 如果不写完整包名,编译器不知道这里要 new 的是哪个 Driver 类
// Driver driver = new Driver();  // 这行代码会报错

// 使用完整包名明确指定要创建的是 MySQL 的 Driver 类实例
Driver driver = new com.mysql.cj.jdbc.Driver(); 

②不依赖导入声明

通常我们可以使用 import 语句导入特定的类,这样在代码中就可以直接使用简单类名。但使用完整包名时,即使没有使用 import 语句导入该类,也能正常创建对象。 例如,下面的代码没有使用 import 语句导入 com.mysql.cj.jdbc.Driver 类,但依然可以通过完整包名来创建该类的实例:

public class WithoutImportExample {
    public static void main(String[] args) {
        java.sql.Driver driver = new com.mysql.cj.jdbc.Driver();
        // 这里不需要在文件开头 import com.mysql.cj.jdbc.Driver;
    }
}

⑷.思考2:以上代码中哪些是JDBC接口,哪些是JDBC接口的实现?

2.JDBC编程第二步:获取连接

获取java.sql.Connection对象,该对象的创建标志着mysql进程和jvm进程之间的通道打开了。

⑴.代码实现

API帮助文档

import java.sql.DriverManager;
import java.sql.Driver;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
public class Main {
    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://192.168.152.236:3306/jdbc";
            String user = "root";
            String password = "abc123";
            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接口来调用方法的。面向接口编程在这里体现的淋漓尽致。确实降低了耦合度。

以上程序中演示了连接数据库需要提供三个信息:url,用户名,密码。其中用户名和密码容易理解。url是什么?

⑵.什么是URL

URL 是统一资源定位符 (Uniform Resource Locator) 的缩写,是互联网上标识、定位、访问资源的字符串。它可以用来指定互联网上各种类型的资源的位置,如网页、图片、视频等。

URL 通常由协议、服务器名、服务器端口、路径和查询字符串组成。其中:

  • 协议是规定了访问资源所采用的通信协议,例如 HTTP、HTTPS、FTP 等;
  • 服务器名是资源所在的服务器主机名或 IP 地址,可以是域名或 IP 地址;
  • 服务器端口是资源所在的服务器的端口号;
  • 路径是资源所在的服务器上的路径、文件名等信息;
  • 查询字符串是向服务器提交的参数信息,用来定位更具体的资源。

URL 在互联网中广泛应用,比如在浏览器中输入 URL 来访问网页或下载文件,在网站开发中使用 URL 来访问 API 接口或文件,在移动应用和桌面应用中使用 URL 来访问应用内部的页面或功能,在搜索引擎中使用 URL 来爬取网页内容等等。

总之,URL 是互联网上所有资源的唯一识别标识,是互联网通信的基础和核心技术之一。

 

⑶.JDBC连接MySQL时的URL格式


JDBC URL 是在使用 JDBC 连接数据库时的一个 URL 字符串,它用来标识要连接的数据库的位置、认证信息和其他配置参数等。JDBC URL 的格式可以因数据库类型而异,但通常包括以下几个部分:

  • 协议:表示要使用的数据库管理系统(DBMS)的类型,如 jdbc:mysql 表示要使用 MySQL 数据库,jdbc:postgresql 表示要使用 PostgreSQL 数据库。
  • 主机地址和端口号:表示要连接的数据库所在的服务器的 IP 地址或域名,以及数据库所在服务器监听的端口号。
  • 数据库名称:表示要连接的数据库的名称。
  • 其他可选参数:这些参数包括连接的超时时间、使用的字符集、连接池相关配置等。

例如,连接 MySQL 数据库的 JDBC URL 的格式一般如下:

jdbc:mysql://<host>:<port>/<database_name>?<connection_parameters>

其中:

<host> 是 MySQL 数据库服务器的主机名或 IP 地址;

<port> 是 MySQL 服务器的端口号(默认为 3306);

<database_name> 是要连接的数据库名称;

<connection_parameters> 包括连接的额外参数,例如用户名、密码、字符集等。

JDBC URL 是连接数据库的关键,通过 JDBC URL,应用程序可以通过特定的 JDBC 驱动程序与数据库服务器进行通信,从而实现与数据库的交互。在开发 Web 应用和桌面应用时,使用 JDBC URL 可以轻松地连接和操作各种类型的数据库,例如 MySQL、PostgreSQL、Oracle 等。

jdbc:mysql://是协议

localhost表示连接本地主机的MySQL数据库,也可以写作127.0.0.1

3306是MySQL数据库的端口号

jdbc是数据库实例名

⑷.MySQL URL中的其它常用配置

在 JDBC MySQL URL 中,常用的配置参数有:

  • serverTimezoneMySQL 服务器时区,默认为 UTC,可以通过该参数来指定客户端和服务器的时区;在 JDBC URL 中设置 serverTimezone 的作用是指定数据库服务器的时区。这个时区信息会影响 JDBC 驱动在处理日期时间相关数据类型时如何将其映射到服务器上的日期时间值。如果不设置 serverTimezone,则 JDBC 驱动程序默认将使用本地时区,也就是客户端机器上的系统时区,来处理日期时间数据。在这种情况下,如果服务器的时区和客户端机器的时区不同,那么处理日期时间数据时可能会出现问题,从而导致数据错误或不一致。

例如,假设服务器位于美国加州,而客户端位于中国上海,如果不设置 serverTimezone 参数,在客户端执行类似下面的查询:

SELECT * FROM orders WHERE order_date = '2022-11-11';

由于客户端和服务器使用了不同的时区,默认使用的是客户端本地的时区,那么实际查询的时间就是客户端本地时间对应的时间,而不是服务器的时间。这可能会导致查询结果不正确,因为服务器上的时间可能是比客户端慢或者快了多个小时。
通过在 JDBC URL 中设置 serverTimezone 参数,可以明确告诉 JDBC 驱动程序使用哪个时区来处理日期时间值,从而避免这种问题。在上述例子中,如果把时区设置为 America/Los_Angeles(即加州的时区):

jdbc:mysql://localhost:3306/mydatabase?user=myusername&password=mypassword&serverTimezone=America/Los_Angeles

useSSL:是否使用 SSL 进行连接,默认为 true;

useSSL 参数用于配置是否使用 SSL(Secure Sockets Layer)安全传输协议来加密 JDBC 和 MySQL 数据库服务器之间的通信。其设置为 true 表示使用 SSL 连接,设置为 false 表示不使用 SSL 连接。其区别如下:

当设置为 true 时,JDBC 驱动程序将使用 SSL 加密协议来保障客户端和服务器之间的通信安全。这种方式下,所有数据都会使用 SSL 加密后再传输,可以有效防止数据在传输过程中被窃听、篡改等安全问题出现。当然,也要求服务器端必须支持 SSL,否则会连接失败。

当设置为 false 时,JDBC 驱动程序会以明文方式传输数据,这种方式下,虽然数据传输的速度会更快,但也会存在被恶意攻击者截获和窃听数据的风险。因此,在不安全的网络环境下,或是要求数据传输安全性较高的情况下,建议使用 SSL 加密连接。

需要注意的是,使用 SSL 连接会对系统资源和性能消耗有一定的影响,特别是当连接数较多时,对 CPU 和内存压力都比较大。因此,在性能和安全之间需要权衡,根据实际应用场景合理设置 useSSL 参数。

  • useUnicode:是否使用Unicode编码进行数据传输,默认是true启用

useUnicode是 JDBC 驱动程序连接数据库时的一个参数,用于告诉驱动程序在传输数据时是否使用 Unicode 编码。Unicode 是计算机科学中的一种字符编码方案,可以用于表示全球各种语言中的字符,包括 ASCII 码、中文、日文、韩文等。因此,使用 Unicode 编码可以确保数据在传输过程中能够正确、完整地呈现各种语言的字符。

具体地说,如果设置 useUnicode=true,JDBC 驱动程序会在传输数据时使用 Unicode 编码。这意味着,无论数据源中使用的是什么编码方案,都会先将数据转换为 Unicode 编码进行传输,确保数据能够跨平台、跨数据库正确传输。当从数据库中获取数据时,驱动程序会根据 characterEncoding 参数指定的字符集编码将数据转换为指定编码格式,以便应用程序正确处理数据。

需要注意的是,如果设置 useUnicode=false,则表示使用当前平台默认的字符集进行数据传输。这可能会导致在跨平台或跨数据库时出现字符编码不一致的问题,因此通常建议在进行数据传输时启用 Unicode 编码。

综上所述,设置 useUnicode 参数可以确保数据在传输过程中正确呈现各种字符集编码。对于应用程序处理多语言环境数据的场景,启用 useUnicode 参数尤为重要。

  • characterEncoding:连接使用的字符编码,默认为 UTF-8;

characterEncoding 参数用于设置 MySQL 服务器和 JDBC 驱动程序之间进行字符集转换时使用的字符集编码。其设置为 UTF-8 表示使用 UTF-8 编码进行字符集转换,设置为 GBK 表示使用 GBK 编码进行字符集转换。其区别如下:

UTF-8 编码是一种可变长度的编码方式,可以表示世界上的所有字符,包括 ASCII、Unicode 和不间断空格等字符,是一种通用的编码方式。UTF-8 编码在国际化应用中被广泛使用,并且其使用的字节数较少,有利于提高数据传输的效率和节约存储空间。

GBK 编码是一种固定长度的编码方式,只能表示汉字和部分符号,不能表示世界上的所有字符。GBK 编码通常只用于中文环境中,因为在英文和数字等字符中会出现乱码情况。

因此,在 MySQL 中使用 UTF-8 编码作为字符集编码的优势在于能够支持世界上的所有字符,而且在国际化应用中使用广泛,对于不同语言和地区的用户都能够提供良好的支持。而使用 GBK 编码则主要在于适用于中文环境中的数据存储和传输。

需要注意的是,在选择编码方式时需要考虑到应用本身的实际需要和数据的特性,根据具体情况进行选择,避免出现字符集编码错误的问题。同时,还要确保 MySQL 服务器、JDBC 驱动程序和应用程序之间的字符集编码一致,避免出现字符集转换错误的问题。

注意:useUnicode和characterEncoding有什么区别?

  • useUnicode设置的是数据在传输过程中是否使用Unicode编码方式。
  • characterEncoding设置的是数据被传输到服务器之后,服务器采用哪一种字符集进行编码。

例如,连接 MySQL 数据库的 JDBC URL 可以如下所示:

jdbc:mysql://localhost:3306/jdbc?useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf-8

这里演示的是使用本地 MySQL 数据库,使用Unicode编码进行数据传输,服务器时区为 Asia/Shanghai,启用 SSL 连接,服务器接收到数据后使用 UTF-8 编码。

3.JDBC编程第三步:获取数据库操作对象

数据库操作对象是这个接口:java.sql.Statement。这个对象负责将SQL语句发送给数据库服务器,服务器接收到SQL后进行编译,然后执行SQL。

API帮助文档如下:

获取数据库操作对象代码如下:

import java.sql.DriverManager;
import java.sql.Driver;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
public class Main {
    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://192.168.152.236:3306/jdbc";
            String user = "root";
            String password = "abc123";
            Connection conn = DriverManager.getConnection(url, user, password);

            // 3. 获取数据库操作对象
            Statement stmt1 = conn.createStatement();
            System.out.println("数据库操作对象stmt = " + stmt1);
            // 3. 获取数据库操作对象
            Statement stmt2 = conn.createStatement();
            System.out.println("数据库操作对象stmt = " + stmt2);


            
        } catch(SQLException e){
            e.printStackTrace();
        }
    }
}

运行结果:

同样可以看到:java.sql.Statement接口在MySQL驱动中的实现类是:com.mysql.cj.jdbc.StatementImpl。不过我们同样是不需要关心这个具体的实现类。因为后续的代码仍然是面向Statement接口写代码的。

另外,要知道的是通过一个Connection对象是可以创建多个Statement对象的:

4.JDBC编程第四步:执行SQL

当获取到Statement对象后,调用这个接口中的相关方法即可执行SQL语句。

API帮助文档如下:

// 返回值的含义:当sql语句是一个DQL语句的时候,并且查询到了结果,返回true。
// 当sql语句是dml语句或者没有查询到任何结果的时候,返回false。
// 这个方法功能比较广泛(不够专业),适合所有的SQL语句,很少用。
//boolean isSuccess = stmt.execute(sql);

代码实现如下:

import java.sql.DriverManager;
import java.sql.Driver;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
public class Main {
    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://192.168.152.236:3306/jdbc";
            String user = "root";
            String password = "abc123";
            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();
        }
    }
}

运行结果:

⑴.executeUpdate() 方法在 Statement 接口中的定义如下:

int executeUpdate(String sql) throws SQLException;

在 PreparedStatement 中,该方法定义为

int executeUpdate() throws SQLException;

参数说明

Statement 中的 executeUpdate(String sql):该方法接受一个 String 类型的参数 sql,表示要执行的 SQL 语句。

PreparedStatement 中的 executeUpdate():由于 PreparedStatement 在创建时已经预编译了 SQL 语句,因此该方法不需要传入 SQL 语句参数。

返回值

该方法返回一个 int 类型的值,表示受 SQL 语句影响的行数。具体解释如下:

①对于 INSERT、UPDATE 和 DELETE 等 DML 语句,返回值是受影响的行数。例如,如果执行一个 UPDATE 语句更新了 5 条记录,那么该方法将返回 5。

②对于 CREATE TABLE、ALTER TABLE、DROP TABLE 等 DDL 语句,返回值通常为 0,因为这些语句不影响具体的行数。

③如果 SQL 语句没有返回任何结果,也会返回 0。

6.JDBC编程第六步:释放资源

第五步去哪里了?第五步是处理查询结果集,以上操作不是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.DriverManager;
import java.sql.Driver;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
public class Main {
    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://192.168.152.236:3306/jdbc";
            String user = "root";
            String password = "abc123";
           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();
                }

        }
        }

    }}

运行结果:

四、注册驱动的常用方式

上面在注册驱动的时候,执行了这样的代码:

java.sql.Driver driver = new com.mysql.cj.jdbc.Driver();
java.sql.DriverManager.registerDriver(driver);

这种方式是自己new驱动对象,然后调用DriverManager的registerDriver()方法来完成驱动注册,还有另一种方式,并且这种方式是常用的:

Class.forName("com.mysql.cj.jdbc.Driver");

为什么这种方式常用?

第一:代码少了很多。
第二:这种方式可以很方便的将com.mysql.cj.jdbc.Driver类名配置到属性文件当中。

实现原理是什么?找一下com.mysql.cj.jdbc.Driver的源码:

通过源码不难发现,在com.mysql.cj.jdbc.Driver类中有一个静态代码块,在这个静态代码块中调用了java.sql.DriverManager.registerDriver(new Driver());完成了驱动的注册。而Class.forName("com.mysql.cj.jdbc.Driver");代码的作用就是让com.mysql.cj.jdbc.Driver类完成加载,执行它的静态代码块

编写代码测试一下:

package oop3;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;

public class JDBCtest03 {
    public static void main(String[] args){
        Connection conn = null;
        Statement stmt = null;
        try {
            // 1. 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2. 获取连接
            String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf-8";
            String user = "root";
            String password = "abc123";
            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 | ClassNotFoundException 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();
                }
            }
        }
    }
}

执行结果:

五、JDBC 4.0后不用手动注册驱动(了解)

从JDBC 4.0(也就是Java6)版本开始,驱动的注册不需要再手动完成,由系统自动完成

package oop3;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;

public class JDBCtest03 {
    public static void main(String[] args){
        Connection conn = null;
        Statement stmt = null;
        try {
            // 2. 获取连接
            String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf-8";
            String user = "root";
            String password = "abc123";
            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();
                }
            }
        }
    }
}

运行结果:

注意:虽然大部分情况下不需要进行手动注册驱动了,但在实际的开发中有些数据库驱动程序不支持自动发现功能,仍然需要手动注册。所以建议大家还是别省略了。

六、动态配置连接数据库的信息

为了程序的通用性,为了切换数据库的时候不需要修改Java程序,为了符合OCP开闭原则,建议将连接数据库的信息配置到属性文件中,例如:

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc?useUnicode=true&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf-8
user=root
password=abc123

package oop3;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ResourceBundle;

public class JDBCtest04 {
    public static void main(String[] args){

        // 通过以下代码获取属性文件中的配置信息
        ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
        String driver = bundle.getString("driver");
        String url = bundle.getString("url");
        String user = bundle.getString("user");
        String password = bundle.getString("password");

        Connection conn = null;
        Statement stmt = null;
        try {
            // 1. 注册驱动
            Class.forName(driver);

            // 2. 获取连接
            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 | ClassNotFoundException 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();
                }
            }
        }
    }
}

运行结果:

七、获取连接的其他方式(了解)

上面我们讲到了第一种获取连接的方式:

Connection conn = DriverManager.getConnection(url, user, password);

除了以上的这种方式之外,还有两种方式,通过API帮助文档可以看到:

1. getConnection(String url)

这种方式参数只有一个url,那用户名和密码放在哪里呢?可以放到url当中,代码如下:

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;

public class JDBCTest05 {
    public static void main(String[] args){
        try {
            // 1. 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2. 获取连接
            String url = "jdbc:mysql://localhost:3306/jdbc?user=root&password=abc123";
            Connection conn = DriverManager.getConnection(url);

            System.out.println("连接对象:" + conn);
        } catch(SQLException|ClassNotFoundException e){
            e.printStackTrace();
        }
    }
}

2.getConnection(String url, Properties info)

这种方式有两个参数,一个是url,一个是Properties对象。

  • url:可以单纯提供一个url地址
  • info:可以将url的参数存放到该对象中

代码如下:

import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.util.Properties;

public class JDBCTest06 {
    public static void main(String[] args){
        try {
            // 1. 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            // 2. 获取连接
            String url = "jdbc:mysql://localhost:3306/jdbc";

            //Properties是Map集合对象
            Properties info = new Properties();
            info.setProperty("user", "root");
            info.setProperty("password", "abc123");
            info.setProperty("useUnicode", "true");
            info.setProperty("serverTimezone", "Asia/Shanghai");
            info.setProperty("useSSL", "true");
            info.setProperty("characterEncoding", "utf-8");

            Connection conn = DriverManager.getConnection(url, info);

            System.out.println("连接对象:" + conn);
        } catch(SQLException|ClassNotFoundException e){
            e.printStackTrace();
        }
    }
}

运行结果:


http://www.kler.cn/a/582309.html

相关文章:

  • C++学习笔记(十七)——类之封装
  • LETTERS(dfs)
  • Spring 的三种注入方式?
  • Vue3 + Spring Boot前后端分离项目跨域问题完整解决方案
  • C++编程:进阶阶段—4.2对象
  • Spring MVC 工作原理和流程
  • ubuntu中用docker下载opengauss
  • 大语言模型中Token的输出过程
  • git设置本地仓库和远程仓库
  • Linux第0节:Linux环境的搭建
  • 003-SpringCloud Alibaba-Nacos(配置中心)
  • 【redis】布隆过滤器的Java实现
  • leetcode日记(93)从中序与后序遍历序列构造二叉树
  • C 语言数据结构(三):栈和队列
  • 【3D视觉学习笔记1】针孔相机模型与坐标系变换
  • Linux进程管理15 - CFS调度器2 - 数据结构关系
  • c#25/3/11 周二
  • WHAT - 前端性能监控和错误追踪(Sentry 篇)
  • 【A2DP】蓝牙A2DP协议剖析:从架构到规范
  • 2025-03-11 学习记录--C/C++-PTA 习题11-5 指定位置输出字符串