【JDBC】详解 Java 中的 JDBC 技术

1. 什么是 JDBC?

JDBC 是什么?来看看文档说明:

The Java Database Connectivity (JDBC) API provides universal data access from the Java programming language. Using the JDBC API, you can access virtually any data source, from relational databases to spreadsheets and flat files. JDBC technology also provides a common base on which tools and alternate interfaces can be built.

大致意思:Java数据库连接(JDBC) API提供了来自Java编程语言的通用数据访问。使用JDBC API,您几乎可以访问任何数据源,从关系数据库到电子表格和平面文件。JDBC技术还提供了构建工具和替代接口的公共基础。

简单来说,JDBC 就是通过 Java 语言来操作数据库(执行 SQL 语句)


2. JDBC 原理

来看看文档怎么说?

To use the JDBC API with a particular database management system, you need a JDBC technology-based driver to mediate between JDBC technology and the database. Depending on various factors, a driver might be written purely in the Java programming language or in a mixture of the Java programming language and Java Native Interface (JNI) native methods. To obtain a JDBC driver for a particular database management system, see JDBC Data Access API.

大致意思:要在特定的数据库管理系统中使用 JDBC API,您需要一个基于 JDBC 技术的驱动程序来充当 JDBC 技术和数据库之间的中介。根据各种因素,驱动程序可以纯用 Java 编程语言编写,也可以混合使用 Java 编程语言和 Java 本机接口(JNI)本机方法编写。

早期 SUN 公司的天才们想编写一套可以连接天下所有数据库的 API,但是当他们刚刚开始时就发现这是不可完成的任务,因为各个厂商的数据库服务器(mysql 数据库服务器、oracle 数据库服务器)差异太大了。后来 SUN 开始与数据库厂商们讨论,最终得出的结论是:由 SUN 提供一套访问数据库的规范(一组接口),并提供连接数据库的协议标准,然后各个数据库厂商会遵循 SUN 的规范提供一套访问自己公司的数据库服务器的 AP I实现。SUN提供的规范命名为 JDBC,而各个厂商提供的,遵循了JDBC规范的,可以访问自己数据库的 API 被称之为驱动!

JDBC 只是一套规范接口,真正实现的是下面的各种驱动:
在这里插入图片描述

没有驱动无法完成数据库连接!每个数据库厂商都有自己的驱动,用来连接自己公司的数据库。

文档还说明:

The JDBC API is comprised of two packages:

  • java.sql
  • javax.sql

You automatically get both packages when you download the Java Platform Standard Edition (Java SE) 8.

JDBC API 位于 jdk 8 中的 java.sql、javax.sql 包下

3. JDBC 核心类/接口介绍

JDBC 中的核心类/接口有:DriverManager、Connection、Statement/PreparedStatement、ResultSet

DriverManager:驱动管理器。负责加载各种不同驱动程序(Driver)

  1. 注册驱动:让 JDBC 知道要使用的是哪个驱动
  2. 获取连接对象:根据不同的请求,向调用者返回相应的数据库连接(Connection)

Connection:数据库连接对象。与数据库的通讯都是通过这个对象展开的

  1. 获取Statement对象

Statement:数据库操作对象。向数据库发送 SQL 语句(静态)。这样数据库就会执行发送过来的 SQL 语句

  1. void executeUpdate(String sql):执行更新操作(insert、update、delete等)
  2. ResultSet executeQuery(String sql):执行查询操作。查询结果就是ResultSet

PreparedStatement:预编译声明。它是 Statement 的子接口

  1. prepareStatement(String sql):创建它时就让它与一条SQL模板绑定
  2. 调用 PreparedStatement的setXXX()系列方法为问号设置值
  3. 调用 executeUpdate()或executeQuery()方法,但要注意,调用没有参数的方法

ResultSet:对象表示查询结果集。只有在执行查询操作后才会有结果集的产生。结果集是一个二维的表格,有行有列。操作结果集要学习移动 ResultSet 内部的“行光标”,以及获取当前行上的每一列上的数据。

  1. boolean next():使“行光标”移动到下一行,并返回移动后的行是否存在
  2. XXX getXXX(int col):获取当前行指定列上的值,参数就是列数,列数从1开始,而不是0

4. JDBC 案例

这里使用 mysql 数据库服务器来做一个查询操作。

public class DBUtil {

    private static final String JDBC_URL = "jdbc:mysql://127.0.0.1:3306/zzc?characterEncoding=UTF-8";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "root";

    // 获取数据库连接
    public static Connection getConnection() {
        Connection conn = null;
        try {
            // 1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            try {
                conn = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD);
            } catch (SQLException e) {
                System.out.println("数据库连接失败");
            }
        } catch (ClassNotFoundException e) {
            System.out.println("驱动包不存在");
        }
        return conn;
    }

    // 关闭连接
    public static void close(Connection conn, Statement stst, ResultSet rs) {
        if (null != conn) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (null != stst) {
            try {
                stst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (null != rs) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

注册驱动

上面的代码中,注册驱动时使用的是 “Class.forName(“com.mysql.jdbc.Driver”);”,那么要为什么是这样的写法?

先查看 DriverManager.registerDriver(java.sql.Driver) 方法,java.sql.Driver 是一个接口,其实现类是由 mysql 驱动提供。其实现类为 “com.mysql.jdbc.Driver”。那么注册驱动的代码本应该为:

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

再来看看 com.mysql.jdbc.Driver 类:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

上述代码确实可以注册驱动,但是会出现以下问题:

  1. 出现硬编码,以致应用程序与驱动包无法解耦。如果以后修改为 oracle 数据库,那么需要修改源代码
  2. 这种注册驱动方式会将 com.mysql.jdbc.Driver() 对象创建两次,完全没必要

JDBC 中规定,驱动类在被加载时,需要自己“主动”把自己注册到 DriverManger 中。如上的 Driver 类的源码:

static 代码块中,会创建 Driver 对象,并且注册到 DriverManager 中。

这说明只要去加载 com.mysql.jdbc.Driver 类,那么就会执行这个 static 块,从而也就会把com.mysql.jdbc.Driver 注册到 DriverManager 中,所以可以把注册驱动类的代码修改为加载驱动类。即:

Class.forName("com.mysql.jdbc.Driver");
public class DBTest {

    public void selectAll() {
        String sql = "SELECT * FROM user";

        Connection conn = null;
        PreparedStatement prst = null;
        ResultSet rs = null;

        try {
            conn = DBUtil.getConnection();
            prst = conn.prepareStatement(sql);
            rs = prst.executeQuery();
            int row = 0;

            while (rs.next()) {
                row++;
                int id = rs.getInt(1);
                String name = rs.getString(2);
                int sex = rs.getInt(3);

                System.out.println("================第" + row + "行");
                System.out.print(id + ",");
                System.out.print(name + ",");
                System.out.println(sex);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, prst, rs);
        }
    }

    public static void main(String[] args) {
        DBTest dbTest = new DBTest();
        dbTest.selectAll();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值