程序员潇然 发表于 2022-8-27 17:02:44

Connection 对象简介 方法解读 JDBC简介(四)

通过驱动管理器DriverManager的getConnection方法,可以创建到指定URL的连接

Connection conn = DriverManager.getConnection(url, user, password);
看得出来,**在JDBC中连接被抽象为Connection**

**表示:与特定数据库的连接(会话)**

**在连接上下文中执行 SQL 语句并返回结果**

!(data/attachment/forum/202208/27/164535pt727v9yle0qco1q.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

### 方法梗概

对于应用程序开发者来说,连接Connection主要用于执行对象的获取从而进一步执行SQL,这是**应用程序与数据库交互的主要途径**

然后提供了数据库事务相关信息的设置以及其他信息的设置与获取

!(data/attachment/forum/202208/27/164635w2t2qq1nbc1qwyeb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

#### 执行对象

用于将 SQL 语句发送到数据库中

对象有三种

**Statement**

* 作用:用于执行不带参数的简单 SQL 语句
* 特点:**每次执行 SQL 语句,数据库都要执行 SQL 语句的编译**,仅执行一次查询并返回结果的情形建议使用这个,此时效率高于 PreparedStatement

**PreparedStatement**

* 作用:用于执行带 或 不带参数的预编译 SQL 语句
* 特点:是**预编译的**, 在执行可变参数的一条 SQL 语句时,比 Statement 的效率高,安全性好,有效防止 SQL 注入等问题,对于多次重复执行的语句,效率会更高

**CallableStatement**

* 作用:用于执行对数据库**存储过程** 的调用

#### 事务

**Connection提供了对于事务相关操作的支持**

事务有自动提交的特性可以设置,自动提交默认每条SQL将会单独一个事务,Connection提供了自动提交属性的查询方法

如果不是自动提交,那么将会延续到手动COMMIT或者ROLLBACK

还能够设置和获取事务的隔离性

另外还可以灵活的设置保存点,从而让一个事务分割成几部分,可以部分提交

#### 连接属性

连接本身有一些属性信息,比如目录等

其中最重要的就是Connection的关闭,数据库的连接是有限的,Connection在使用完毕后需要进行关闭

另外还提供了连接状态的测试方法

#### 小结

Connection最为基础的方法就是执行对象的创建以及事务相关以及连接属性相关的

其他方法属于对于数据库本身能力的API支持。

### 重点方法简介

#### 执行对象

**静态执行对象创建createStatement**

```java
//创建一个 Statement 对象来将 SQL 语句发送到数据库。
Statement createStatement();

//创建一个 Statement 对象,该对象将生成具有给定类型和并发性的 ResultSet 对象。
Statement createStatement(int resultSetType, int resultSetConcurrency);

//创建一个 Statement 对象,该对象将生成具有给定类型、并发性和可保存性的 ResultSet 对象。
Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability);
```

**createStatement的核心是为了创建Statement,不带参数的 SQL 语句通常使用 Statement 对象执行;**

**如果多次执行相同的 SQL 语句,使用 PreparedStatement 对象可能更有效。**

三个版本的createStatement核心是一样的,**区别在于参数的设置,参数的设置是针对于结果集的**

空参数的createStatement返回的Statement 对象,创建的结果集在默认情况下类型为 TYPE_FORWARD_ONLY,并带有 CONCUR_READ_ONLY 并发级别

已创建结果集的可保存性可调用 **getHoldability()** 确定

**resultSetType** - 以下 ResultSet 常量之一:

```java
ResultSet.TYPE_FORWARD_ONLY

ResultSet.TYPE_SCROLL_INSENSITIVE

ResultSet.TYPE_SCROLL_SENSITIVE
```

**resultSetConcurrency** - 以下 ResultSet 常量之一:

```java
ResultSet.CONCUR_READ_ONLY

ResultSet.CONCUR_UPDATABLE
```

**resultSetHoldability** - 以下 ResultSet 常量之一:

```java
ResultSet.HOLD_CURSORS_OVER_COMMIT

ResultSet.CLOSE_CURSORS_AT_COMMIT
```

**简言之,createStatement系列用于创建Statement--通常用来执行不带参数的SQL,并且附带的可以设置结果集的类型、并发性、可保存性**

**动态执行对象创建prepareStatement**

```java
//创建一个 PreparedStatement 对象来将参数化的 SQL 语句发送到数据库。
PreparedStatement prepareStatement(String sql);

//创建一个默认 PreparedStatement 对象,该对象能获取自动生成的键。
PreparedStatement prepareStatement(String sql, int autoGeneratedKeys);

//创建一个能返回由给定数组指定的自动生成键的默认 PreparedStatement 对象。
PreparedStatement prepareStatement(String sql, int[] columnIndexes);

// 创建一个能返回由给定数组指定的自动生成键的默认 PreparedStatement 对象。
PreparedStatement prepareStatement(String sql, String[] columnNames);

//创建一个 PreparedStatement 对象,该对象将生成具有给定类型和并发性的 ResultSet 对象。
PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency);

//创建一个 PreparedStatement 对象,该对象将生成具有给定类型、并发性和可保存性的 ResultSet 对象。
PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)


```

prepareStatement系列方法创建一个 PreparedStatement 对象来将参数化的 SQL 语句发送到数据库。

**1. prepareStatement(String sql) 最为基础的创建方法**

带有 IN 参数或不带有 IN 参数的 SQL 语句都可以被预编译并存储在 PreparedStatement 对象中。然后**可以有效地使用此对象来多次执行该语句**。

**结果集属性在默认情况下类型为 TYPE_FORWARD_ONLY,并带有 CONCUR_READ_ONLY 并发级别。**

已创建结果集的可保存性可调用 **getHoldability()** 确定。

!(data/attachment/forum/202208/27/165259dsb3si6b8s07bsz6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

**2. 返回键值数据**

prepareStatement(String sql, int autoGeneratedKeys)

创建一个默认 PreparedStatement 对象,**该对象能获取自动生成的键**

**autoGeneratedKeys - 指示是否应该返回自动生成的键的标志,它是 Statement.RETURN_GENERATED_KEYS 或 Statement.NO_GENERATED_KEYS 之一**

通过设置Statement.RETURN_GENERATED_KEYS要求返回主键

通过getGeneratedKeys方法,获取结果集,进而可以获取主键

此处插入一条记录,所以主键返回必然只有一个,当试图获取不存在的下标时,将会抛出异常,如下面所示,读取rs.getInt(2);时就报错了

!(data/attachment/forum/202208/27/165318m833c18u1akr30a3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

另外还可以使用int数组指定列下标,或者String数组指定列名,指明用于返回的键

`prepareStatement(String sql, int[] columnIndexes)`

`prepareStatement(String sql, String[] columnNames)`

注意:

**这几个方法并不是说所有的数据库都支持都一样,比如对于MYSQL来说,都是一回事**

`本文作者:程序员潇然 疯狂的字节X https://crazybytex.com/`

!(data/attachment/forum/202208/27/165339bulrnz6796ukv2d1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

通过测试代码我们也可以看得出来,随便设置的数组,也都无所谓,因为mysql压根就没关注数组的内容(上面的代码为mysql的实现)

!(data/attachment/forum/202208/27/165353zvvp2p8b40qpvvcp.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

**类似createStatement 也有可以设置结果集类型、并发性、可保存性的方法**

```java
PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency);

PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability);
```

resultSetType - 以下 ResultSet 常量之一:

```java
ResultSet.TYPE_FORWARD_ONLY

ResultSet.TYPE_SCROLL_INSENSITIVE

ResultSet.TYPE_SCROLL_SENSITIVE
```

`resultSetConcurrency` - 以下 ResultSet 常量之一:

```java
ResultSet.CONCUR_READ_ONLY

ResultSet.CONCUR_UPDATABLE
```

`resultSetHoldability` - 以下 ResultSet 常量之一:

```java
ResultSet.HOLD_CURSORS_OVER_COMMIT

ResultSet.CLOSE_CURSORS_AT_COMMIT
```

**默认情况下类型为 TYPE_FORWARD_ONLY,并带有 CONCUR_READ_ONLY 并发级别。**

已创建结果集的可保存性可调用 **getHoldability()** 确定。

这一点还是那样子,如果没设置的,存在默认值

**存储过程执行对象创建CallableStatement**

```java
//创建一个 CallableStatement 对象来调用数据库存储过程。
CallableStatement prepareCall(String sql);

//创建一个 CallableStatement 对象,该对象将生成具有给定类型和并发性的 ResultSet 对象。
CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency);

//创建一个 CallableStatement 对象,该对象将生成具有给定类型和并发性的 ResultSet 对象。
CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability);
```

**核心为创建存储过程的执行对象,另外与createStatement和prepareStatement方法类似,可以设置结果集的类型、并发性、可保存性。**

#### 事务

支持事务的数据库一般都有自动提交,提交、回滚、保存点、事务隔离级别这几个基本属性。

Connection中提供了对他们的支持。

```java
//获取此 Connection 对象的当前自动提交模式。
boolean getAutoCommit();

//使所有上一次提交/回滚后进行的更改成为持久更改,并释放此 Connection 对象当前持有的所有数据库锁。
void commit();

//取消在当前事务中进行的所有更改,并释放此 Connection 对象当前持有的所有数据库锁。
void rollback();

//取消所有设置给定 Savepoint 对象之后进行的更改。
void rollback(Savepoint savepoint);

//将此连接的自动提交模式设置为给定状态。
void setAutoCommit(boolean autoCommit);
      
//试图将此 Connection 对象的事务隔离级别更改为给定的级别。
void setTransactionIsolation(int level);

//获取此 Connection 对象的当前事务隔离级别。
int getTransactionIsolation();

//在当前事务中创建一个未命名的保存点 (savepoint),并返回表示它的新 Savepoint 对象。
Savepoint setSavepoint();

//在当前事务中创建一个具有给定名称的保存点,并返回表示它的新 Savepoint 对象。
Savepoint setSavepoint(String name);

//从当前事务中移除指定的 Savepoint 和后续 Savepoint 对象。
void releaseSavepoint(Savepoint savepoint);
```


#### 连接自身属性状态

Connection最重要的一个状态就是打开与关闭,通过getConnection方法如果连接成功,那么该连接被打开

在使用结束之后你需要手动进行关闭


```java
//立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们被自动释放。
void close();

//JDBC还提供了查询方法用于检测该连接是否已经被关闭。查询此 Connection 对象是否已经被关闭。
boolean isClosed();

//另外还有检测连接是否有效的方法,如果连接尚未关闭并且仍然有效,则返回 true。
boolean isValid(int timeout);
```

本文作者:程序员潇然 疯狂的字节X https://crazybytex.com/


### 总结

Connection主要用于创建SQL的执行对象,而连接通过驱动管理器DriverManager的getConnection方法进行获取。

Connection并不是所有的方法都如API描述的一模一样,要看具体的驱动程序的支持情况

比如前面提到的MYSQL对于prepareStatement(String sql, String[] columnNames)和prepareStatement(String sql, int[] columnIndexes)的情况

通过连接对执行对象的创建,决定了很多事情

比如执行语句的特质,是用来执行静态SQL还是预编译带参数的动态的SQL还是存储过程?

也可以对结果集的参数进行设置

事务的相关处理也是在连接中操作的。

通过连接还能够获得数据库的元数据信息

我们所有的查询都是在一个数据库连接中进行的,所以此次操作所需要的东西,比如sql设置、结果集属性设置再或者数据库相关的元数据信息等都可以通过Connection获得。

!(data/attachment/forum/202206/16/141330jha7st9soow8772i.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "common_log.png")
`转载务必注明出处:程序员潇然,疯狂的字节X,https://crazybytex.com/thread-171-1-1.html `
页: [1]
查看完整版本: Connection 对象简介 方法解读 JDBC简介(四)