## Connection - [Connection](#connection) - [一、基本信息](#一基本信息) - [二、基本描述](#二基本描述) - [三、主要功能](#三主要功能) - [四、接口源码](#四接口源码) - [六、最佳实践](#六最佳实践) ### 一、基本信息 ✒️ **作者** - Lex 📝 **博客** - [掘金](https://juejin.cn/user/4251135018533068/posts) 📚 **源码地址 ** - [github](https://github.com/xuchengsheng/spring-reading) ### 二、基本描述 `Connection` 接口是 Java JDBC API 中的一部分,代表着与数据库的连接。它提供了方法来管理数据库连接、执行 SQL 语句以及处理事务,是与数据库交互的重要接口之一。 ### 三、主要功能 1. **执行 SQL 语句** + 通过 `createStatement()` 方法创建 `Statement` 对象,或者通过 `prepareStatement(String sql)` 方法创建 `PreparedStatement` 对象,用于执行 SQL 查询、更新或删除等操作。 2. **事务管理** + 支持事务操作,可以通过 `commit()` 提交事务或者 `rollback()` 回滚事务。 3. **设置事务属性** + 可以设置事务的隔离级别、自动提交等属性。 ### 四、接口源码 `Connection` 接口,用于表示与特定数据库的连接。它提供了方法来执行 SQL 语句、管理事务、提交或回滚更改以及关闭连接。 ```java /** *

表示与特定数据库的连接(会话)。SQL 语句在连接的上下文中执行并返回结果。 *

* Connection 对象的数据库能够提供描述其表、支持的 SQL 语法、存储的过程、连接的功能等信息。这些信息是通过 getMetaData 方法获取的。 * *

注意:在配置 Connection 时,JDBC 应用程序应使用适当的 Connection 方法,如 setAutoCommitsetTransactionIsolation。应用程序不应直接调用 SQL 命令来更改连接的配置,而应使用 JDBC 方法。默认情况下,Connection 对象处于自动提交模式,这意味着它在执行每个语句后会自动提交更改。如果已禁用自动提交模式,则必须显式调用 commit 方法才能提交更改;否则,数据库更改将不会保存。 *

* 使用 JDBC 2.1 核心 API 创建的新的 Connection 对象具有一个最初为空的类型映射。用户可以为此类型映射中的用户定义类型(UDT)输入自定义映射。 * 当从数据源检索到 UDT 并使用 ResultSet.getObject 方法时,getObject 方法将检查连接的类型映射以查看是否存在该 UDT 的条目。如果存在,则 getObject 方法将把 UDT 映射到指定的类。如果不存在条目,则使用标准映射映射 UDT。 *

* 用户可以创建一个新的类型映射,它是一个 java.util.Map 对象,向其中添加一个条目,并将其传递给可以执行自定义映射的 java.sql 方法。在这种情况下,方法将使用给定的类型映射而不是与连接关联的类型映射。 *

* 例如,以下代码片段指定 SQL 类型 ATHLETES 将映射到 Java 编程语言中的类 Athletes。该代码片段检索 Connection 对象 con 的类型映射,将条目插入其中,然后将带有新条目的类型映射设置为连接的类型映射。 *

 *      java.util.Map map = con.getTypeMap();
 *      map.put("mySchemaName.ATHLETES", Class.forName("Athletes"));
 *      con.setTypeMap(map);
 * 
* * @see DriverManager#getConnection * @see Statement * @see ResultSet * @see DatabaseMetaData * @since 1.1 */ public interface Connection extends Wrapper, AutoCloseable { /** * 创建一个用于向数据库发送 SQL 语句的 Statement 对象。 * 通常使用 Statement 对象执行无参数的 SQL 语句。如果相同的 SQL 语句需要执行多次,使用 PreparedStatement 对象可能更有效率。 *

* 使用返回的 Statement 对象创建的结果集默认为 TYPE_FORWARD_ONLY 类型,并且并发级别为 CONCUR_READ_ONLY。可以通过调用 {@link #getHoldability} 来确定创建的结果集的可保持性。 * * @return 一个新的默认 Statement 对象 * @exception SQLException 如果发生数据库访问错误,或者在关闭的连接上调用此方法 */ Statement createStatement() throws SQLException; /** * 创建一个用于向数据库发送参数化 SQL 语句的 PreparedStatement 对象。 *

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

注意:此方法针对处理受益于预编译的参数化 SQL 语句进行了优化。如果驱动程序支持预编译,则方法 prepareStatement 将向数据库发送语句进行预编译。某些驱动程序可能不支持预编译。在这种情况下,直到执行 PreparedStatement 对象时,语句才会被发送到数据库。这对用户没有直接影响;但是,它影响了哪些方法会抛出某些 SQLException 对象。 *

* 使用返回的 PreparedStatement 对象创建的结果集默认为 TYPE_FORWARD_ONLY 类型,并且并发级别为 CONCUR_READ_ONLY。可以通过调用 {@link #getHoldability} 来确定创建的结果集的可保持性。 * * @param sql 可能包含一个或多个 '?' IN 参数占位符的 SQL 语句 * @return 包含预编译的 SQL 语句的新的默认 PreparedStatement 对象 * @exception SQLException 如果发生数据库访问错误,或者在关闭的连接上调用此方法 */ PreparedStatement prepareStatement(String sql) throws SQLException; /** * 使自上次提交/回滚以来所做的所有更改永久,并释放此 Connection 对象当前持有的任何数据库锁定。 * 只有在禁用自动提交模式时才应该使用此方法。 * * @exception SQLException 如果发生数据库访问错误,如果在参与分布式事务时调用此方法,如果在关闭的连接上调用此方法或者此 Connection 对象处于自动提交模式下 * @see #setAutoCommit */ void commit() throws SQLException; /** * 撤消当前事务中所做的所有更改,并释放此 Connection 对象当前持有的任何数据库锁定。 * 只有在禁用自动提交模式时才应该使用此方法。 * * @exception SQLException 如果发生数据库访问错误,如果在参与分布式事务时调用此方法,如果在关闭的连接上调用此方法或者此 Connection 对象处于自动提交模式下 * @see #setAutoCommit */ void rollback() throws SQLException; /** * 立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们自动释放。 *

* 对已关闭的 Connection 对象调用 close 方法是一个无操作。 *

* 强烈建议在调用 close 方法之前显式地提交或回滚活动事务。如果调用了 close 方法且存在活动事务,则结果是由实现定义的。 * * @exception SQLException 如果发生数据库访问错误 */ void close() throws SQLException; // .... } ``` ### 六、最佳实践 使用 Java JDBC API 连接到数据库,并执行插入操作。它首先配置了一个 `DataSource` 对象,用于连接到 MySQL 数据库。然后,它使用这个数据源获取了一个数据库连接,并设置了不自动提交,开启了一个事务。接着,它准备了一个 SQL 插入语句,并创建了一个 `PreparedStatement` 对象来执行插入操作。在执行插入操作后,它提交了事务,并打印了影响的行数。如果在执行过程中发生了异常,它会回滚事务并打印异常信息。最后,它处理了关闭连接时可能发生的异常。 ```java public class ConnectionDemo { public static void main(String[] args) { // 使用 DataSource 体现了高内聚,有利于后面更改数据库 MysqlDataSource dataSource = new MysqlDataSource(); // 数据库连接 URL,格式为 jdbc:数据库驱动名称://主机地址:端口号/数据库名称 dataSource.setUrl("jdbc:mysql://localhost:3306/spring-reading"); // 数据库用户名 dataSource.setUser("root"); // 数据库密码 dataSource.setPassword("123456"); try (Connection connection = dataSource.getConnection()) { // 设置不自动提交,开启事务 connection.setAutoCommit(false); // SQL 插入语句 String sql = "insert into scores(score) values(?)"; // 创建 PreparedStatement 对象,用于执行 SQL 插入操作 try (PreparedStatement statement = connection.prepareStatement(sql)) { // 设置参数 statement.setInt(1, new Random().nextInt(100)); // 执行插入操作 int row = statement.executeUpdate(); // 模拟异常,用于测试事务回滚 // int i = 1 / 0; // 提交事务 connection.commit(); // 打印影响行数 System.out.println("row = " + row); } catch (Exception e) { // 发生异常时回滚事务 connection.rollback(); // 打印异常信息 e.printStackTrace(); } } catch (SQLException e) { // 处理关闭连接异常 e.printStackTrace(); } } } ```