Java 基础知识之 JDBC

什么是 JDBC

JDBC 全称 Java DataBase Connection,是 Java 定义的一套访问关系型数据库的规范,实现由各数据库厂商来完成,通过这套 API,Java 开发者可以轻松的访问各数据库。

如何通过 JDBC 访问数据库

通过 JDBC 访问数据库有一套固定的模板,查询数据库的示例代码如下。

		String url = "jdbc:mysql://127.0.0.1:3306/test";
        String username = "root";
        String password = "12345678";
        // 1. 获取连接
        Connection connection = DriverManager.getConnection(url, username, password);
        // 2. 获取查询语句
        PreparedStatement preparedStatement = connection.prepareStatement("select * from test");
        // 3. 执行查询,获取结果集
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()){
        	// 4. 从结果集取数据
            int id = resultSet.getInt("id");
            System.out.println(id);
        }
        // 5. 关闭连接
        resultSet.close();
        preparedStatement.close();
        connection.close();

上述代码中涉及到了一些 JDBC 相关的 API,下面加以介绍。

JDBC 提供了哪些 API 抽象?

驱动

为了操作数据库,我们需要先获取一个数据库的连接,驱动的作用正是获取某一个数据库的连接,JDBC 支持一个程序中同时存在多个驱动,驱动在 JDBC 中对应的接口是java.sql.Driver,驱动由驱动管理器java.sql.DriverManager进行管理,下面进行单独介绍。

java.sql.Driver

Driver 作为一个接口,由具体的数据库厂商进行实现,在加载驱动时,驱动将创建自己的实例并向驱动管理器进行注册,因此我们经常看到一些类似Class.forName("com.mysql.cj.jdbc.Driver")的代码。以 MySQL 为例,实现为com.mysql.cj.jdbc.Driver,代码如下。

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
  
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

    public Driver() throws SQLException {
      
    }
}

MySQL 的驱动在静态代码块中添加了向驱动管理器注册自身的逻辑,因此调用Class.forName("com.mysql.cj.jdbc.Driver")方法后驱动管理器就对 MySQL 的驱动进行管理。

下面为 Driver 接口中的一些相对来说比较重要的方法,分别加以介绍。

方法作用
Connection connect(String url, java.util.Properties info) throws SQLExceptionDriver 的核心方法,尝试建立给定 url 的数据库连接,不支持给定的 url 时返回 null,因为 DriverManager 会将 url 传递到每一个 Driver 尝试获取连接,连接遇到问题时抛出异常, 属性应至少包含 user 和 password
boolean acceptsURL(String url) throws SQLException驱动是否支持给定的 url 连接
DriverPropertyInfo[] getPropertyInfo(String url, java.util.Properties info) throws SQLException获取驱动所需的属性信息,如 host、port、database、user、password

Driver 获取 Connection 的示例代码如下。

        String url = "jdbc:mysql://127.0.0.1:3306/test";
        String username = "root";
        String password = "12345678";
        Driver driver = new com.mysql.cj.jdbc.Driver();
        Properties properties = new Properties();
        properties.put("user", username);
        properties.put("password", password);
        Connection connection = driver.connect(url, properties);
        connection.close();

java.sql.DriverManager

DriverManager 是 Driver 的管理器,提供了注册驱动、取消注册驱动、获取连接等方法,有了 DriverManager 之后,我们每次获取连接时就不用再关心使用哪个具体的 Driver。先看 DriverManager 提供的主要方法。

方法作用
public static synchronized void registerDriver(Driver driver) throws SQLException向驱动管理器注册驱动,每个驱动在初始化时都要向驱动管理器注册自己,如上述中的 MySQL 驱动
public static synchronized void registerDriver(Driver driver, DriverAction da) throws SQLException向驱动管理器注册驱动,DriverAction 用于接收取消注册驱动的回调
public static synchronized void deregisterDriver(Driver driver)向驱动管理器取消注册驱动
public static Connection getConnection(String url, Properties info) throws SQLException使用给定的 url 获取 Connection
public static Connection getConnection(String url, String user, String password) throws SQLException使用给定的 url 获取 Connection
public static Connection getConnection(String url) throws SQLException使用给定的 url 获取驱动
public static Driver getDriver(String url)获取支持给定 url 的已注册驱动

从上面的方法中可以看到,DriverManager 的作用就是管理 Driver,进一步抽象 Connection 的获取,DriverManager 会从已注册的驱动中尝试获取 Connection。如果只是提供 Driver 的注册和取消注册方法,那么使用 DriverManager 获取 Connection 前,使用方仍然要关心 Driver 的具体实现,为了解决这个问题,DriverManager 初始化时会尝试初始化 Driver,具体有两种方式,感兴趣的小伙伴可自行阅读源码。

  1. 初始化 jdbc.dirvers 系统属性指定的 Driver,多个 Driver 使用:分割。
  2. JDBC 4 开始利用 SPI 机制初始化 Driver。关于 SPI 机制,可参考我前面的文章 《Java 基础知识之 SPI》

有了 SPI 机制之后,我们只需要引入具体数据库的驱动即可,而不用再调用Class.forName("com.mysql.cj.jdbc.Driver")方法。MySQL 的驱动目前已支持 SPI 。
在这里插入图片描述
最后,再上一段 DriverManager 获取 Connection 的示例代码。

		// Class.forName("com.mysql.cj.jdbc.Driver") 不再需要调用该方法初始化驱动
		String url = "jdbc:mysql://127.0.0.1:3306/test";
        String username = "root";
        String password = "12345678";
        Connection connection = DriverManager.getConnection(url, username,password);
        connection.close();

数据源

不管是 Driver 还是 DriverManager,最终都要获取连接,JDBC 2.0 开始,提出一个数据源的概念,也是用于获取连接,其接口为javax.sql.DataSource,其上只定义两个获取连接的方法,具体如下。

public interface DataSource  extends CommonDataSource, Wrapper {

  Connection getConnection() throws SQLException;

  Connection getConnection(String username, String password) throws SQLException;
}

目前有两个使用较多的数据源,分别是 HiKariCP 和 Druid 。感兴趣的小伙伴可自行研究。

连接

连接在 JDBC API 的抽象是java.sql.Connection,表示客户端和某一种具体数据库之间的会话,连接提供的 API 大概可分为如下几类。

1. 获取 Statement 的 API
Statement 用于执行 SQL,后面会进行介绍,这里先看有哪些获取 Statement 的方法。

    
    /**
     * 创建一个可以生成给定类型、并发性、保持性的 ResultSet 的 Statement
     * 默认的结果集类型是 ResultSet.TYPE_FORWARD_ONLY,
     * 默认的并发性是 ResultSet.CONCUR_READ_ONLY,
     * 默认的保持性可以调用 #getHoldability 方法获取
     *
     * @param resultSetType 		结果集类型,可取值为 ResultSet.TYPE_FORWARD_ONLY、ResultSet.TYPE_SCROLL_INSENSITIVE、ResultSet.TYPE_SCROLL_SENSITIVE
     * @param resultSetConcurrency 	结果集的并发性,可取值为 ResultSet.CONCUR_READ_ONLY,ResultSet.CONCUR_UPDATABLE
     * @param resultSetHoldability 	结果集的保持性,可取的值为 ResultSet.HOLD_CURSORS_OVER_COMMIT、ResultSet.CLOSE_CURSORS_AT_COMMIT
     */
    Statement createStatement() throws SQLException;
    Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException;
    Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException;

    /**
     * 创建 PreparedStatement
     * 默认的结果集类型是 ResultSet.TYPE_FORWARD_ONLY,
     * 默认的并发性是 ResultSet.CONCUR_READ_ONLY,
     * 默认的保持性可以调用 #getHoldability 方法获取
     *
     * @param sql 					要发送到数据库的 SQL ,可以包含多个 ? 作为参数
     * @param resultSetType 		结果集类型,可取值为 ResultSet.TYPE_FORWARD_ONLY、ResultSet.TYPE_SCROLL_INSENSITIVE、ResultSet.TYPE_SCROLL_SENSITIVE
     * @param resultSetConcurrency 	结果集的并发性,可取值为 ResultSet.CONCUR_READ_ONLY,ResultSet.CONCUR_UPDATABLE
     * @param resultSetHoldability 	结果集的保持性,可取的值为 ResultSet.HOLD_CURSORS_OVER_COMMIT、ResultSet.CLOSE_CURSORS_AT_COMMIT
     * @param autoGeneratedKeys 	返回的 PreparedStatement 是否可以获取自动生成的键,可取值为 Statement.RETURN_GENERATED_KEYS、Statement.NO_GENERATED_KEYS
     * @param columnIndexes 		目标表中列的索引,指示返回的 PreparedStatement 可以获取到自动生成的哪些键
     * @param columnNames 			目标表中的列名,指示返回的 PreparedStatement 可以获取到自动生成的哪些键
     */
    PreparedStatement prepareStatement(String sql)throws SQLException;
    PreparedStatement prepareStatement(String sql, int resultSetType,  int resultSetConcurrency) throws SQLException;
    PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException;
    PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException;
    PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SQLException;
    PreparedStatement prepareStatement(String sql, String columnNames[]) throws SQLException;

    /**
     * 创建一个可以生成给定类型、并发性、保持性的 ResultSet 的 CallableStatement
     * 默认的结果集类型是 ResultSet.TYPE_FORWARD_ONLY,
     * 默认的并发性是 ResultSet.CONCUR_READ_ONLY,
     * 默认的保持性可以调用 #getHoldability 方法获取
     *
     * @param sql 					要发送到数据库的 SQL ,可以包含多个 ? 作为参数
     * @param resultSetType 		结果集类型,可取值为 ResultSet.TYPE_FORWARD_ONLY、ResultSet.TYPE_SCROLL_INSENSITIVE、ResultSet.TYPE_SCROLL_SENSITIVE
     * @param resultSetConcurrency 	结果集的并发性,可取值为 ResultSet.CONCUR_READ_ONLY,ResultSet.CONCUR_UPDATABLE
     * @param resultSetHoldability 	结果集的保持性,可取的值为 ResultSet.HOLD_CURSORS_OVER_COMMIT、ResultSet.CLOSE_CURSORS_AT_COMMIT
     */	
	CallableStatement prepareCall(String sql) throws SQLException;
	CallableStatement prepareCall(String sql, int resultSetType,  int resultSetConcurrency) throws SQLException;
	CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException;

2. 事务相关的 API

// 事务隔离级别:不支持事务隔离级别
int TRANSACTION_NONE             = 0;
// 事务隔离级别:读未提交
int TRANSACTION_READ_UNCOMMITTED = 1;
// 事务隔离级别:读已提交
int TRANSACTION_READ_COMMITTED   = 2;
// 事务隔离级别:可重复度
int TRANSACTION_REPEATABLE_READ  = 4;
// 事务隔离级别:序列号
int TRANSACTION_SERIALIZABLE     = 8;

// 设置事务隔离级别
void setTransactionIsolation(int level) throws SQLException;
// 获取事务隔离级别
int getTransactionIsolation() throws SQLException;

// 设置是否自动提交事务,默认情况执行完一条 SQL 后自动提交事务
void setAutoCommit(boolean autoCommit) throws SQLException;
// 获取是否自动提交事务
boolean getAutoCommit() throws SQLException;

// 提交事务
void commit() throws SQLException;
// 回滚事务
void rollback() throws SQLException;

// 设置事务的保存点,在事务内创建 rollback 将返回到该保存点,事务外创建新的事务将从该保存点开始
Savepoint setSavepoint() throws SQLException;
Savepoint setSavepoint(String name) throws SQLException;

3. 创建 JDBC 数据类型实例的 API
JDBC 中的数据类型并非每个关系型数据库都支持,数据类型后面加以介绍,Connection 可以创建的数据类型如下。

Clob createClob() throws SQLException;
Blob createBlob() throws SQLException;
NClob createNClob() throws SQLException;
SQLXML createSQLXML() throws SQLException;
Array createArrayOf(String typeName, Object[] elements) throws SQLException;
Struct createStruct(String typeName, Object[] attributes) throws SQLException;

4. 其他 API

// 获取数据库的元数据
DatabaseMetaData getMetaData() throws SQLException;

// 设置/获取客户端的信息
void setClientInfo(Properties properties) throws SQLClientInfoException;
Properties getClientInfo() throws SQLException;

// 终止/关闭打开的连接
void abort(Executor executor) throws SQLException;
void close() throws SQLException;
// 连接是否已经关闭
boolean isClosed() throws SQLException;

// 清除/获取数据库访问的警告信息
void clearWarnings() throws SQLException;
SQLWarning getWarnings() throws SQLException;

// 连接是否仍有效,即未关闭
boolean isValid(int timeout) throws SQLException;

// 设置/获取驱动等待数据库请求完成的毫秒数
void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException;
int getNetworkTimeout() throws SQLException;

// 设置/获取连接是否用于只读
void setReadOnly(boolean readOnly) throws SQLException;
boolean isReadOnly() throws SQLException;

// 设置/获取当前连接到的数据库
void setSchema(String schema) throws SQLException;
String getSchema() throws SQLException;

// 设置/获取当前连接创建的 Statement 可以获取到的 ResultSet 的保持性
void setHoldability(int holdability) throws SQLException;
int getHoldability() throws SQLException;

语句

Statement 用于执行 SQL,返回执行结果 ResultSet,主要分为三种,分别是 Statement、PreparedStatement、CallableStatement,下面分别加以介绍。

Statement

Statement 用于执行静态 SQL 语句,并返回其产生的结果。默认情况下每个 Statement 只能打开一个 ResultSet,如果存在打开的 ResultSet ,则再次执行语句会甘比当前的 ResultSet,Statement 提供的方法如下。

1. 执行单条 SQL

// 执行查询语句
ResultSet executeQuery(String sql) throws SQLException;

// 执行更新语句,第二个参数表示是否可以获取自动生成的键或者指定获取哪些自动生成的键
int executeUpdate(String sql) throws SQLException;
int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException;
int executeUpdate(String sql, int columnIndexes[]) throws SQLException;
int executeUpdate(String sql, String columnNames[]) throws SQLException;

// 执行普通的 sql,增删改查都可以,第二个参数指定执行更新语句后可以获取哪些自动生成的键
boolean execute(String sql) throws SQLException;
boolean execute(String sql, int autoGeneratedKeys) throws SQLException;
boolean execute(String sql, int columnIndexes[]) throws SQLException;
// 使用 #execute 方法执行查询语句后,可以调用该方法获取查询结果
ResultSet getResultSet() throws SQLException;
// 使用 #execute 方法执行更新语句后,可以调用该方法获取更新的记录数量
int getUpdateCount() throws SQLException;

// 执行 #executeQuery 或 #execute 方法后判断是否还有更多的结果集
boolean getMoreResults() throws SQLException;
// 获取更多的结果集
boolean getMoreResults(int current) throws SQLException;
// 调用 #executeUpdate 或 #execute 方法执行更新语句后获取自动生成的键
ResultSet getGeneratedKeys() throws SQLException;

2. 批量执行 SQL

// 将 sql 添加到批量待执行的列表
void addBatch( String sql ) throws SQLException;
// 清除待批量执行的 sql
void clearBatch() throws SQLException;
// 批量执行 sql
int[] executeBatch() throws SQLException;

// 获取更新的数量
default long getLargeUpdateCount() throws SQLException
// 设置/获取执行查询语句后生成的 ResultSet 最大包含的行数 
default void setLargeMaxRows(long max) throws SQLException
default long getLargeMaxRows() throws SQLException
// 批量执行 sql
default long[] executeLargeBatch() throws SQLException
// 批量执行更新语句
default long executeLargeUpdate(String sql) throws SQLException
default long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException
default long executeLargeUpdate(String sql, int columnIndexes[]) throws SQLException
default long executeLargeUpdate(String sql, String columnNames[]) throws SQLException

3. 其他方法

// 获取/设置执行查询语句生成的 ResultSet 中字符和二进制值的列的最大字节数
int getMaxFieldSize() throws SQLException;
void setMaxFieldSize(int max) throws SQLException;
// 获取执行查询语句生成的 ResultSet 中最大的行数
int getMaxRows() throws SQLException;
// 设置是否处理转义字符
void setEscapeProcessing(boolean enable) throws SQLException;
// 获取/设置查询超时秒数
int getQueryTimeout() throws SQLException;
void setQueryTimeout(int seconds) throws SQLException;
// 取消查询
void cancel() throws SQLException;
// 获取/清除当前语句执行产生的警告信息
SQLWarning getWarnings() throws SQLException;
void clearWarnings() throws SQLException;
// 设置游标名称
void setCursorName(String name) throws SQLException;
// 设置游标方向
void setFetchDirection(int direction) throws SQLException;
int getFetchDirection() throws SQLException;
// 设置数据库每次返回的记录条数
void setFetchSize(int rows) throws SQLException;
int getFetchSize() throws SQLException;
// 获取执行查询语句后生成的 ResultSet 的并发性、类型、保持性
int getResultSetConcurrency() throws SQLException;
int getResultSetType()  throws SQLException;
int getResultSetHoldability() throws SQLException;
// 获取当前语句对应的连接
Connection getConnection()  throws SQLException;
// 当前语句是否已经关闭
boolean isClosed() throws SQLException;
// 设置/获取当前语句是否被池化
void setPoolable(boolean poolable) throws SQLException;
boolean isPoolable() throws SQLException;
// 设置/获取当前语句依赖的 ResultSet 全部完毕后是否关闭当前语句
public void closeOnCompletion() throws SQLException;
public boolean isCloseOnCompletion() throws SQLException;

PreparedStatement

PreparedStatement 继承了 Statement,表示预编译 SQL 语句,SQL 会保存在 PreparedStatement 对象中从而可以多次执行。提供了大量用于设置 sql 参数的 set 方法,需要注意的是调用的 set 方法的参数的类型需要和数据库兼容。PreparedStatement 中常用的方法如下。

// 执行查询语句
ResultSet executeQuery() throws SQLException;
// 执行更新语句
int executeUpdate() throws SQLException;
// 清空当前的参数值
void clearParameters() throws SQLException;
// 执行 SQL语句,获取结果集可以调用 #getResultSet,获取更新行数可以调用 #getUpdateCount,判断是否还有结果集可以调用 #getMoreResults
boolean execute() throws SQLException;
// 将设置的参数添加到批量执行的命令中
void addBatch() throws SQLException;
// 执行批量更新
default long executeLargeUpdate() throws SQLException
// 获取结果集的元数据
ResultSetMetaData getMetaData() throws SQLException;
// 获取参数的元数据
ParameterMetaData getParameterMetaData() throws SQLException;

// 将指定的参数设置为 null
void setNull(int parameterIndex, int sqlType) throws SQLException;

/**
 * 将指定的参数设置为指定的值,值的类型需要和数据库兼容,Xxx 可取的值及对应的 JDBC 类型如下:
 * Boolean -> BIT 或 BOOLEAN
 * Byte -> TINYINT
 * Short -> SMALLINT
 * Int -> INTEGER
 * Long -> BIGINT
 * Float -> REAL
 * Double -> DOUBLE
 * 
 */
void setXxx(int parameterIndex, xxx x) throws SQLException;

/**
 * 将指定的参数设置为指定的值,值的类型需要和数据库兼容,Xxx 可取的值及对应的 JDBC 类型如下:
 * BigDecimal -> NUMERIC
 * String -> VARCHAR 或 LONGVARCHAR
 * Date -> DATE
 * Time -> TIME
 * Timestamp -> TIMESTAMP
 */
void setXxx(int parameterIndex, Xxx x) throws SQLException;

// 将指定的参数设置为字节数组值,发送到数据库时将转换为 VARBINARY 或 LONGVARBINARY
void setBytes(int parameterIndex, byte x[]) throws SQLException;
// 将指定的参数设置为给定的值,发送到数据库时将转换为对应的 SQL 类型
void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException;
void setObject(int parameterIndex, Object x) throws SQLException;

CallableStatement

CallableStatement 继承 PreparedStatement,是一个用于执行存储过程的接口,在 PreparedStatement 的基础上添加了注册和获取输出参数的方法,执行前注册输出参数,执行后就可以获取到输出参数的值。常用的方法如下。

// 注册输出参数
void registerOutParameter(int parameterIndex, int sqlType) throws SQLException;
void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException;
default void registerOutParameter(int parameterIndex, SQLType sqlType) throws SQLException
default void registerOutParameter(int parameterIndex, SQLType sqlType, int scale) throws SQLException
default void registerOutParameter(int parameterIndex, SQLType sqlType, String typeName) throws SQLException
default void registerOutParameter(String parameterName, SQLType sqlType) throws SQLException
default void registerOutParameter(String parameterName, SQLType sqlType, int scale) throws SQLException
default void registerOutParameter(String parameterName, SQLType sqlType, String typeName) throws SQLException 

// 检查上次调用 getXxx 方法获取的输出参数是否为 SQL null
boolean wasNull() throws SQLException;

// 获取输出参数,其中 XXX 可表示的类型包括 boolean、byte、double、float、int、long、short、Object、String、Date、Time、Timestamp、Array、BigDecimal 等
Xxx getXxx(int parameterIndex) throws SQLException;
Xxx getXxx(String parameterName) throws SQLException;

// 将指定参数设置为给定的值,XXX 可表示的类型包括 boolean、byte、double、float、int、long、short、Object、Date等
void setXxx(String parameterName, xxx x) throws SQLException;

结果集

ResultSet 是执行查询语句后生成的表示查询结果的数据表。它维护了一个指向当前数据行的游标,默认位于第一行之前,使用 #next 方法可以将光标移动到下一行,当没有更多行的时候返回 false。默认的 ResultSet 不能更新,游标只能向前移动,因此只能从第一行遍历到最后一行。ResultSet 提供了一些 getXxx 方法用于从当前行中获取列的值。在 JDBC 2.0 时,ResultSet 中添加了 一些 updateXxx 方法,用于更新当前行中的值。生成 ResultSet 的 Statement 关闭、执行新语句、获取下一个 ResultSet 时,当前 ResultSet 对象将会被关闭。具体涉及常用的方法如下。

1. 遍历记录的方法

// 将游标向前移动一行,默认游标在第一行之前,第一次调用会使第一行成为当前行,返回 false 时表示游标已经位于最后一行之后。
boolean next() throws SQLException;

// 获取当前行中列的值,Xxx 可取的类型包括 String、boolean、byte、short、int、long、float、double、Date、Time、Timestamp、Object 等,列的索引从1开始
Xxx getXxx(int columnIndex) throws SQLException;

// 获取当前行中列的值,Xxx 可取的类型包括 String、boolean、byte、short、int、long、float、double、Date、Time、Timestamp、Object 等,columnLabel 表示 列名或 as 语句指定的别名
Xxx getXxx(String columnLabel) throws SQLException;

// 根据列标签查询列索引
int findColumn(String columnLabel) throws SQLException;
// 游标是否在第一行之前
boolean isBeforeFirst() throws SQLException;
// 游标是否在最后一行之后
boolean isAfterLast() throws SQLException;
// 游标是否在第一行
boolean isFirst() throws SQLException;
// 游标是否在最后一行
boolean isLast() throws SQLException;
// 将游标移动到第一行之前
void beforeFirst() throws SQLException;
// 将游标移动到最后一行之后
void afterLast() throws SQLException;
// 将游标移动到第一行
boolean first() throws SQLException;
// 将游标移动到最后一行
boolean last() throws SQLException;
// 获取当前行号,行号从第一行开始
int getRow() throws SQLException;
// 移动游标到给定的行号
boolean absolute( int row ) throws SQLException;
// 移动游标到相对于当前行的给定行数的位置
boolean relative( int rows ) throws SQLException;
// 移动游标到上一行
boolean previous() throws SQLException;

2. 更新记录的方法

// 将给定列更新为空值
void updateNull(int columnIndex) throws SQLException;

// 将给定的列更新为给定的值,Xxx 可取的类型包括 Boolean、Byte、Short、Int、Long、Float、Double、BigDecimal、String、Date、Time、Timestamp、Object 等
void updateXxx(int columnIndex, xxx x) throws SQLException;

// 将给定的列更新为给定的值,Xxx 可取的类型包括 Boolean、Byte、Short、Int、Long、Float、Double、BigDecimal、String、Date、Time、Timestamp、Object 等
void updateXxx(String columnLabel, xxx x) throws SQLException;

// 将游标位置移动到插入行,插入行本质上是一个与可更新 ResultSet 关联的缓冲区
void moveToInsertRow() throws SQLException;
// 将游标移动到当前行,如果游标不在插入行则调用该方法无效
void moveToCurrentRow() throws SQLException;

// 将插入行的内容插入到当前 ResultSet 和数据库,调用此方法时游标需要位于插入行
void insertRow() throws SQLException;
// 将当前行从 ResultSet 和数据库中删除
void deleteRow() throws SQLException;
// 将当前行更新到数据库,位于插入行时不能调用该方法
void updateRow() throws SQLException;
// 使用当前行在数据库中的最新值更新当前行,位于插入行时不能调用该方法
void refreshRow() throws SQLException;
// 取消对当前行的更新,可以在调用 #updateNow 方法之前调用
void cancelRowUpdates() throws SQLException;

// 当前行是否已更新
boolean rowUpdated() throws SQLException;
// 当前行是否有插入
boolean rowInserted() throws SQLException;
// 当前行是否已经被删除
boolean rowDeleted() throws SQLException;

3. 其他方法

// 获取结果集的元数据, 如列的数量、类型、元数据等
ResultSetMetaData getMetaData() throws SQLException;
// 获取游标名称
String getCursorName() throws SQLException;
// 设置/获取游标的方向
void setFetchDirection(int direction) throws SQLException;
int getFetchDirection() throws SQLException;
// 获取 ResultSet 的类型
int getType() throws SQLException;
// 获取 ResultSet 的并发模式
int getConcurrency() throws SQLException;
// 获取生成该 ResultSet 的 Statement
Statement getStatement() throws SQLException;

总结

本篇主要对 JDBC 进行了简单的介绍,其他的内容如数据类型 JDBCType 或 异常 SQLException 等感兴趣的小伙伴可自行研究。JDBC 简化了对关系型数据库的操作,但是同时带来了样板式代码,各种持久层框架都在尝试对其简化,了解其底层的 API 是了解这些持久层框架的基础,后面的文章会尝试对 Mybatis 的底层实现进行解析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大鹏cool

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值