美文网首页
章节 7 JDBC 概念

章节 7 JDBC 概念

作者: 嘟豆豆 | 来源:发表于2019-10-01 00:14 被阅读0次

目录

7.1 使用 JDBC DriverManager 接口连接 MySQL

7.2 使用 JDBC Statement 对象执行 SQL

7.3 使用 JDBC CallableStatements 执行存储过程

7.4 通过 JDBC 检索 AUTO_INCREMENT 列值


本节提供一些常用的 JDBC 场景。

7.1 使用 JDBC DriverManager 接口连接 MySQL

当您在应用程序服务器以外使用 JDBC 时, DriverManager 类管理连接的建立。

尝试使用 JDBC 驱动中特定的 DriverManager 建立连接,最简单的方式是在 java.sql.Driver 接口实现类上,使用 Class.forName() 。在 MySQL Connector/J 中,接口实现类名为 com.mysql.cj.jdbc.Driver 。使用此方法,您可以使用外部配置文件,提供在连接到数据库时,要使用的驱动程序类名和驱动程序参数。

下面的 Java 代码部分展示了如何在您的应用程序 main() 方法中注册 MySQL Connector/J。如果测试此代码,请首先阅读 安装部分 章节 4, Connector/J 安装,以确保正确安装了连接器,并设置了 CLASSPATH 。另外,确保 MySQL 配置为接受外部 TCP/IP 连接。

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

// 注意,不要 import com.mysql.cj.jdbc.*

// 否则你会有麻烦的!

public class LoadDriver {

    public static void main(String[] args) {

        try {

            // newInstance() 调用是为了使的相应的 Java 类实例化。

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

        } catch (Exception ex) {

            // 处理错误

        }

    }

}

在驱动程序注册 DriverManager 之后, 您可以通过调用 DriverManager.getConnection() 来获得 Connection实例,与特定的数据库建立连接 :

示例 7.1 Connector/J: 通过 DriverManager 中获取连接

如果您还没有这样做,请在使用下面的示例之前,查看以上章节 7.1, “使用 JDBC DriverManager 接口连接 MySQL”部分。

此示例显示如何通过 DriverManager ,获取 Connection 实例。 getConnection() 方法,有几种不同的使用方式。具体请参阅 JDK 附带的 API 文档,那里 有如何使用它们的详细信息。

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

Connection conn = null;

...

try {

    conn =

      DriverManager.getConnection("jdbc:mysql://localhost/test?" +

                                  "user=minty&password=greatsqldb");

    // 获取连接后,要做的事

  ...

} catch (SQLException ex) {

    // 处理任何错误

    System.out.println("SQLException: " + ex.getMessage());

    System.out.println("SQLState: " + ex.getSQLState());

    System.out.println("VendorError: " + ex.getErrorCode());

}

Connection 建立后, 就可以使用它来创建 Statement 和 PreparedStatement 对象, 以及检索有关数据库的元数据。后面章节会对此进行说明。

7.2 使用 Statement 对象执行 SQL

Statement 对象允许您执行基本的 SQL 查询, 并通过 ResultSet 类检索结果, 稍后将对此进行描述。

若要创建 Statement 实例, 请您根据上述所言,在 DriverManager.getConnection() 或DataSource.getConnection() 中选择一种方式,获取 Connection 对象,然后调用 createStatement() 方法。

有了 Statement 实例, 您就可以向 executeQuery(String) 方法,并传入你想要使用的SQL,来执行一个 SELECT查询。

要更新数据库中的数据,请使用 executeUpdate(String SQL) 方法。 此方法返回 update 语句匹配的行数,而不是被修改的行数。

如果您事先不知道 SQL 语句是 SELECT 还是 UPDATE/INSERT, 那么可以使用 execute(String SQL) 方法。如果 SQL 查询是 SELECT语句,则此方法将返回 true。 如果是 UPDATE、 INSERT, 或者 DELETE 语句,则返回 false。如果语句是 SELECT 查询,则可以通过调用 getResultSet() 方法检索结果。如果该语句是 UPDATE、 INSERT,或者 DELETE 语句, 则可以通过对 Statement 实例调用 getUpdateCount() 来检索受影响的行数。

示例 7.2 Connector/J: 使用 java.sql.Statement 执行 SELECT 查询

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Statement;

import java.sql.ResultSet;

// 假设 conn 是一个已经创建的 JDBC 连接(参见前面的示例)

Statement stmt = null;

ResultSet rs = null;

try {

    stmt = conn.createStatement();

    rs = stmt.executeQuery("SELECT foo FROM bar");

    // 或者,如果您不提前知道

    // 查询将是一个 SELECT...

    if (stmt.execute("SELECT foo FROM bar")) {

        rs = stmt.getResultSet();

    }

    // 现在对 ResultSet 做些什么....

}

catch (SQLException ex){

    // 处理任何错误

    System.out.println("SQLException: " + ex.getMessage());

    System.out.println("SQLState: " + ex.getSQLState());

    System.out.println("VendorError: " + ex.getErrorCode());

}

finally {

    // 如果不再需要资源,

    // 最好以与创建资源相反的顺序

    // 在 finally{} 块中,

    // 释放资源

    if (rs != null) {

        try {

            rs.close();

        } catch (SQLException sqlEx) { } // 忽略

        rs = null;

    }

    if (stmt != null) {

        try {

            stmt.close();

        } catch (SQLException sqlEx) { } // 忽略

        stmt = null;

    }

}

7.3 使用 JDBC CallableStatements 执行存储过程

Connector/J 完全实现了 java.sql.CallableStatement 接口。

有关 MySQL 存储过程的更多信息,请参阅 使用存储例程 

Connector/J 通过 JDBC 的 CallableStatement 接口显示存储过程功能。

下面的示例显示了一个存储过程,该存储过程返回 inOutParam 的值自增1,并且使用 inputParam ResultSet 作为结果集传入的字符串:

示例 7.3 Connector/J: 调用存储过程

CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), \

                        INOUT inOutParam INT)

BEGIN

    DECLARE z INT;

    SET z = inOutParam + 1;

    SET inOutParam = z;

    SELECT inputParam;

    SELECT CONCAT('zyxw', inputParam);

END

要通过 Connector/J 使用 demoSp 过程,需要执行以下步骤:

使用 Connection.prepareCall() 准备可调用语句。

注意,您必须使用 JDBC 转义语法,并且参数占位符周围的括号不是可选的:

示例 7.4 Connector/J: 使用 Connection.prepareCall()

import java.sql.CallableStatement;

...

    //

    // 使用两个参数准备对

    // 存储过程 'demoSp' 的调用

    //

    // 注意 JDBC 转义语法的使用为 ({call ...})

    //

    CallableStatement cStmt = conn.prepareCall("{call demoSp(?, ?)}");

    cStmt.setString(1, "abcdefg");

说明

Connection.prepareCall() 是一个重量级的方法,因为驱动程序执行元数据检索以支持输出参数。 出于性能原因,通过在代码中重用 CallableStatement 实例,尽量减少对 Connection.prepareCall() 的不必要调用。

注册输出参数(如果有的话)

要检索输出参数(创建存储过程时指定为 OUT 或 INOUT 的参数)的值,JDBC 要求在语句执行之前使用CallableStatement 接口中的各种 registerOutputParameter() 方法指定这些参数:

示例 7.5 Connector/J: 注册输出参数

import java.sql.Types;

...

//

// Connector/J 同时支持命名输出参数和索引输出参数。

// 无论使用何种方法注册它们,

// 您都可以使用任一方法注册输出参数,

// 也可以使用任一方法检索输出参数。

//

// 下面的示例演示

// 如何使用各种注册输出参数的方法

// (当然,每个参数只应注册一次)。

//

//

// 将第二个参数作为输出注册,

// 并对 getObject() 方法返回的值,

// 使用 'INTEGER' 类型接收。

//

cStmt.registerOutParameter(2, Types.INTEGER);

//

// 注册命名参数 'inOutParam',

// 并对 getObject() 方法返回的值,

// 使用 'INTEGER' 类型接收。

//

cStmt.registerOutParameter("inOutParam", Types.INTEGER);

...

设置输入参数(如果有的话)

为 PreparedStatement 对象设置输入/输出参数. 当然, CallableStatement 依然支持按名称设置参数:

示例 7.6 Connector/J: 设置 CallableStatement 输入参数

...

    //

    // 使用索引设置参数

    //

    cStmt.setString(1, "abcdefg");

    //

    // 或者,

    // 使用参数名设置参数

    //

    cStmt.setString("inputParam", "abcdefg");

    //

    // 使用索引设置 '输入/输出' 参数

    //

    cStmt.setInt(2, 1);

    //

    // 或者,

    // 使用参数名设置 '输入/输出' 参数

    //

    cStmt.setInt("inOutParam", 1);

...

执行 CallableStatement ,并检索所有结果集或输出参数。

虽然 CallableStatement 支持调用任意 Statement 执行方法 ( executeUpdate() , executeQuery() 或execute() ),但最灵活的调用方法是 execute() 因为如果存储过程返回结果集,则不需要提前知道:

示例 7.7 Connector/J: 检索结果和输出参数值

...

    boolean hadResults = cStmt.execute();

    //

    // 处理所有返回的结果集

    //

    while (hadResults) {

        ResultSet rs = cStmt.getResultSet();

        // 处理结果集

        ...

        hadResults = cStmt.getMoreResults();

    }

    //

    // 检索输出参数

    //

    // Connector/J 支持基于索引

    // 和基于名称的数据检索

    //

    int outputValue = cStmt.getInt(2); // 基于索引

    outputValue = cStmt.getInt("inOutParam"); // 基于名称

...

7.4 通过 JDBC 检索 AUTO_INCREMENT 列值

如果需要通过 JDBC 检索 AUTO_INCREMENT 关键字,那么 getGeneratedKeys() 是首选方法,这在下面的第一个示例中说明。 第二个示例显示了如何使用标准 SELECT LAST_INSERT_ID() 查询,检索相同的值。最后一个示例演示了当使用 insertRow() 方法时,如何检索可更新结果集的 AUTO_INCREMENT 值。

示例 7.8 Connector/J: 使用 Statement.getGeneratedKeys() 检索 AUTO_INCREMENT 列值

Statement stmt = null;

ResultSet rs = null;

try {

    //

    // 创建一个 Statement 实例,我们可以将其用于

    // 'normal' 结果集,

    // 前提是您已经与 MySQL 数据库

    // 建立了连接 'conn'

    stmt = conn.createStatement();

    //

    // 对示例中表执行 DDL 查询

    //

    stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");

    stmt.executeUpdate(

            "CREATE TABLE autoIncTutorial ("

            + "priKey INT NOT NULL AUTO_INCREMENT, "

            + "dataField VARCHAR(64), PRIMARY KEY (priKey))");

    //

    // 插入一行,将在 'priKey' 字段中,

    // 生成 AUTO INCREMENT 键

    //

    stmt.executeUpdate(

            "INSERT INTO autoIncTutorial (dataField) "

            + "values ('Can I Get the Auto Increment Field?')",

            Statement.RETURN_GENERATED_KEYS);

    //

    // 示例使用 Statement.getGeneratedKeys()

    // 来检索自增的值

    //

    int autoIncKeyFromApi = -1;

    rs = stmt.getGeneratedKeys();

    if (rs.next()) {

        autoIncKeyFromApi = rs.getInt(1);

    } else {

        // 从这里抛出异常

    }

    System.out.println("Key returned from getGeneratedKeys():"

        + autoIncKeyFromApi);

} finally {

    if (rs != null) {

        try {

            rs.close();

        } catch (SQLException ex) {

            // 忽略

        }

    }

    if (stmt != null) {

        try {

            stmt.close();

        } catch (SQLException ex) {

            // 忽略

        }

    }

}

示例 7.9 Connector/J: 使用 SELECT LAST_INSERT_ID() 检索 AUTO_INCREMENT 列值

Statement stmt = null;

ResultSet rs = null;

try {

    //

    // 创建一个可以用于 'normal'结果集的

    // Statement 实例。

    stmt = conn.createStatement();

    //

    // 对示例中表执行 DDL 查询

    //

    stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");

    stmt.executeUpdate(

            "CREATE TABLE autoIncTutorial ("

            + "priKey INT NOT NULL AUTO_INCREMENT, "

            + "dataField VARCHAR(64), PRIMARY KEY (priKey))");

    //

    // 插入一行,将在 'priKey' 字段中,

    // 生成 AUTO INCREMENT 键

    //

    stmt.executeUpdate(

            "INSERT INTO autoIncTutorial (dataField) "

            + "values ('Can I Get the Auto Increment Field?')");

    //

    // 使用 MySQL LAST_INSERT_ID() 函数,

    // 执行与 getGeneratedKeys() 相同的操作。

    //

    int autoIncKeyFromFunc = -1;

    rs = stmt.executeQuery("SELECT LAST_INSERT_ID()");

    if (rs.next()) {

        autoIncKeyFromFunc = rs.getInt(1);

    } else {

        // 从这里抛出异常

    }

    System.out.println("Key returned from " +

                      "'SELECT LAST_INSERT_ID()': " +

                      autoIncKeyFromFunc);

} finally {

    if (rs != null) {

        try {

            rs.close();

        } catch (SQLException ex) {

            // 忽略

        }

    }

    if (stmt != null) {

        try {

            stmt.close();

        } catch (SQLException ex) {

            // 忽略

        }

    }

}

示例 7.10 Connector/J: 在可更新结果集中检索 AUTO_INCREMENT列值

Statement stmt = null;

ResultSet rs = null;

try {

    //

    // 创建一个 Statement 实例,

    // 我们可以将其用于 'normal' 结果集和 'updatable' 结果集,

    // 前提是您已经与 MySQL 数据库,

    // 建立了连接 'conn'

    //

    stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,

                                java.sql.ResultSet.CONCUR_UPDATABLE);

    //

    // 对示例中表执行 DDL 查询

    //

    stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");

    stmt.executeUpdate(

            "CREATE TABLE autoIncTutorial ("

            + "priKey INT NOT NULL AUTO_INCREMENT, "

            + "dataField VARCHAR(64), PRIMARY KEY (priKey))");

    //

    // 示例从可更新的结果集中,

    // 检索 AUTO INCREMENT 键。

    //

    rs = stmt.executeQuery("SELECT priKey, dataField "

      + "FROM autoIncTutorial");

    rs.moveToInsertRow();

    rs.updateString("dataField", "AUTO INCREMENT here?");

    rs.insertRow();

    //

    // 驱动程序在末尾添加行

    //

    rs.last();

    //

    // 我们现在应该在刚才插入的那一行上

    //

    int autoIncKeyFromRS = rs.getInt("priKey");

    System.out.println("Key returned for inserted row: "

        + autoIncKeyFromRS);

} finally {

    if (rs != null) {

        try {

            rs.close();

        } catch (SQLException ex) {

            // 忽略

        }

    }

    if (stmt != null) {

        try {

            stmt.close();

        } catch (SQLException ex) {

            // 忽略

        }

    }

}

运行前面的示例代码应产生以下输出结果:

Key returned from getGeneratedKeys(): 1

Key returned from SELECT LAST_INSERT_ID(): 1

Key returned for inserted row: 1

有时,使用 SELECT LAST_INSERT_ID() 查询可能会很棘手,因为函数的值被限制在连接上。 因此,如果在同一连接上发生了其他查询,则该值会被重写。 另一方面, getGeneratedKeys() 方法由 Statement 实例限定,即使在同一连接上发生其他查询, 但不能在同一 Statement 实例上使用,所以此方法可以被使用。

相关文章

  • 章节 7 JDBC 概念

    目录 7.1 使用 JDBCDriverManager接口连接 MySQL 7.2 使用 JDBCStatemen...

  • java数据库管理之jdbc

    JDBC概念和数据库驱动程序 A: JDBC概念和数据库驱动程序•a: JDBC概述 ◦JDBC(Java Dat...

  • java数据库管理之jdbc

    JDBC概念和数据库驱动程序 A: JDBC概念和数据库驱动程序 a: JDBC概述 JDBC(Java Data...

  • java数据库管理之jdbc

    JDBC概念和数据库驱动程序 A: JDBC概念和数据库驱动程序a: JDBC概述JDBC(Java Data B...

  • java数据库管理之jdbc

    JDBC概念和数据库驱动程序 A: JDBC概念和数据库驱动程序a: JDBC概述JDBC(Java Data B...

  • 一、JDBC

    今日内容 JDBC基本概念 快速入门 对JDBC中各个接口和类详解 一、JDBC概述 概念:Java DataBa...

  • 18/1/22 java数据库管理之jdbc

    JDBC概念和数据库驱动程序 a:JDBC概述*JDBC(Java Data Base Connectivity ...

  • # day10_JDBC基础

    一,JDBC概述 1.为什么要使用JDBC 1.1没有JDBC 1.2有了JDBC后 2.JDBC的概念 2.1....

  • JDBC

    本文主要内容 1、JDBC 2、DBUtils 01JDBC概念和数据库驱动程序 A: JDBC概念和数据库驱动程...

  • Java学习笔记 24 - JDBC技术、DBUtils工具类

    本文主要内容1、JDBC2、DBUtils 01JDBC概念和数据库驱动程序 A: JDBC概念和数据库驱动程序a...

网友评论

      本文标题:章节 7 JDBC 概念

      本文链接:https://www.haomeiwen.com/subject/tltkpctx.html