# 3.4控制数据库连接

本节内容包括：

* 使用DataSource
* 使用DataSourceUtils
* 实现SmartDataSource
* 扩展AbstractDataSource
* 使用SingleConnectionDataSource
* 使用DriverManagerDataSource
* 使用TransactionAwareDataSourceProxy
* 使用DataSourceTransactionManager

## 3.4.1 使用数据源

Spring通过数据源获得与数据库的连接。数据源是JDBC规范的一部分，是通用的连接工厂。它允许容器或框架从应用程序代码中隐藏连接池和事务管理问题。作为开发人员，你无需了解有关如何连接到数据库的详细信息。这是设置数据源的管理员的责任。你很可能在开发和测试代码时同时担当这两个角色，但是不必一定要知道如何配置生产数据源。

使用Spring的JDBC层时，你可以从JNDI获取数据源，也可以使用第三方提供的连接池实现来配置自己的数据源。流行的实现是Apache Jakarta Commons DBCP和C3P0。 Spring发行版中的实现仅用于测试目的，不提供池化。

本部分使用Spring的DriverManagerDataSource实现，稍后将介绍其他一些实现。

> 你应仅将DriverManagerDataSource类用于测试目的，因为它不提供缓冲池，并且在发出多个连接请求时性能不佳。

要配置DriverManagerDataSource：

1. 通常会获得JDBC连接，因此获得与DriverManagerDataSource的连接。
2. 指定JDBC驱动程序的标准类名，以便DriverManager可以加载驱动程序类。
3. 提供在JDBC驱动程序之间变化的URL。 （有关正确的值，请参阅驱动程序的文档。）
4. 提供用户名和密码以连接到数据库。

以下示例显示了如何在Java中配置DriverManagerDataSource：

```java
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");
```

下面是相应的XML配置：

```markup
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>
```

接下来的两个示例显示了DBCP和C3P0的基本连接和配置。 要了解更多有助于控制池功能的选项，请参阅相应连接池实现的产品文档。

以下示例显示了DBCP配置：

```markup
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>
```

下面是C3P0的例子：

```markup
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="${jdbc.driverClassName}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="user" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

<context:property-placeholder location="jdbc.properties"/>
```

## 3.4.2 使用DataSourceUtils

DataSourceUtils类是一种方便且功能强大的帮助器类，它提供静态方法从JNDI获取连接并在必要时关闭连接。它支持使用例如DataSourceTransactionManager进行线程绑定的连接。

## 3.4.3 实施SmartDataSource

SmartDataSource接口应该由可以提供与关系数据库的连接的类来实现。它扩展了DataSource接口，以允许使用它的类查询在给定操作后是否应关闭连接。当你知道需要重用连接时，这种用法很有效。

## 3.4.4 扩展AbstractDataSource

AbstractDataSource是Spring的DataSource实现的抽象基类。它实现了所有DataSource实现通用的代码。如果编写自己的DataSource实现，则应该扩展AbstractDataSource类。

## 3.4.5 使用SingleConnectionDataSource

SingleConnectionDataSource类是SmartDataSource接口的实现，该接口包装了每次使用后都未关闭的单个Connection。这不是多线程功能。

如果假设共享池连接（例如使用持久性工具）时有任何客户端代码调用关闭，则应将preventClose属性设置为true。此设置将返回用于封装物理连接的封闭代理。请注意，你不能再将此对象转换为本地Oracle Connection或类似对象。

SingleConnectionDataSource主要是一个测试类。例如，它结合简单的JNDI环境，可以在应用服务器外部轻松测试代码。与DriverManagerDataSource相比，它始终重用同一连接，避免了过多的物理连接创建。

## 3.4.6 使用DriverManagerDataSource

DriverManagerDataSource类是标准DataSource接口的实现，该接口通过bean属性配置纯JDBC驱动程序，并每次返回一个新的Connection。

此实现对于Java EE容器外部的测试和独立环境非常有用，可以作为Spring IoC容器中的DataSource bean或与简单的JNDI环境结合使用。假定使用池的Connection.close（）调用将关闭连接，因此任何可识别DataSource的持久性代码都应起作用。但是，即使在测试环境中，使用JavaBean风格的连接池（例如commons-dbcp）也是如此容易，以至总是总是最好在DriverManagerDataSource上使用这样的连接池。

## 3.4.7 使用TransactionAwareDataSourceProxy

TransactionAwareDataSourceProxy是目标数据源的代理。代理包装该目标数据源以增加对Spring管理的事务的认识。在这方面，它类似于Java EE服务器提供的事务性JNDI数据源。

> 除非需要调用已经存在的代码并通过标准的JDBC DataSource接口实现，否则很少需要使用此类。 在这种情况下，你仍然可以使该代码可用，同时使该代码参与Spring托管的事务。 通常，最好使用更高级别的资源管理抽象来编写自己的新代码，例如JdbcTemplate或DataSourceUtils。

## 3.4.8 使用DataSourceTransactionManager

DataSourceTransactionManager类是单个JDBC数据源的PlatformTransactionManager实现。它将JDBC连接从指定的数据源绑定到当前正在执行的线程，可能允许每个数据源一个线程连接。

通过DataSourceUtils.getConnection（DataSource）而不是Java EE的标准DataSource.getConnection检索JDBC连接需要应用程序代码。它抛出未经检查的org.springframework.dao异常，而不是经过检查的SQLException。所有框架类（例如JdbcTemplate）都隐式使用此策略。如果不与该事务管理器一起使用，则查找策略的行为与普通策略完全相同。因此，可以在任何情况下使用它。

DataSourceTransactionManager类支持自定义隔离级别和超时，这些隔离级别和超时将作为适当的JDBC语句查询超时应用。为了支持后者，应用程序代码必须使用JdbcTemplate或为每个创建的语句调用DataSourceUtils.applyTransactionTimeout（..）方法。

在单资源情况下，可以使用此实现而不是JtaTransactionManager，因为它不需要容器支持JTA。只要你坚持要求的连接查找模式，就可以在两者之间进行切换只是配置问题。 JTA不支持自定义隔离级别。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flydean.com/spring-framework-documentation5/dataaccess/3.jdbc/3.4controlling-database-connections.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
