Controlling Database Connections
Using DataSource
Spring 通过 DataSource
获取与数据库的连接。DataSource
是 JDBC 规范的一部分,是一个通用的连接工厂。它允许容器或框架对应用程序代码隐藏连接池和事务管理问题。作为开发人员,您不需要了解如何连接到数据库的详细信息。这是设置数据源的管理员的职责。您很可能在开发和测试代码时扮演这两个角色,但您不必一定要知道生产数据源是如何配置的。
Spring obtains a connection to the database through a DataSource
. A DataSource
is
part of the JDBC specification and is a generalized connection factory. It lets a
container or a framework hide connection pooling and transaction management issues
from the application code. As a developer, you need not know details about how to
connect to the database. That is the responsibility of the administrator who sets up
the datasource. You most likely fill both roles as you develop and test code, but you
do not necessarily have to know how the production data source is configured.
当您使用 Spring 的 JDBC 层时,可以从 JNDI 获取数据源,也可以使用第三方提供的连接池实现配置您自己的数据源。传统的选项是用 bean 样式的 DataSource
类的 Apache Commons DBCP 和 C3P0;对于现代 JDBC 连接池,请考虑使用构建器样式 API 的 HikariCP。
When you use Spring’s JDBC layer, you can obtain a data source from JNDI, or you can
configure your own with a connection pool implementation provided by a third party.
Traditional choices are Apache Commons DBCP and C3P0 with bean-style DataSource
classes;
for a modern JDBC connection pool, consider HikariCP with its builder-style API instead.
你应该只将 |
You should use the |
以下部分使用 Spring 的 DriverManagerDataSource
实现。稍后将涵盖其他几个 DataSource
变体。
The following section uses Spring’s DriverManagerDataSource
implementation.
Several other DataSource
variants are covered later.
要配置 DriverManagerDataSource
:
To configure a DriverManagerDataSource
:
-
Obtain a connection with
DriverManagerDataSource
as you typically obtain a JDBC connection. -
Specify the fully qualified class name of the JDBC driver so that the
DriverManager
can load the driver class. -
Provide a URL that varies between JDBC drivers. (See the documentation for your driver for the correct value.)
-
Provide a username and a password to connect to the database.
以下示例展示了如何配置 DriverManagerDataSource
:
The following example shows how to configure a DriverManagerDataSource
:
-
Java
-
Kotlin
-
Xml
@Bean
DriverManagerDataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
@Bean
fun dataSource() = DriverManagerDataSource().apply {
setDriverClassName("org.hsqldb.jdbcDriver")
url = "jdbc:hsqldb:hsql://localhost:"
username = "sa"
password = ""
}
<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 的基本连接性和配置。要了解有关帮助控制池特性的更多选项,请参阅各个连接池实现的产品文档。
The next two examples show the basic connectivity and configuration for DBCP and C3P0. To learn about more options that help control the pooling features, see the product documentation for the respective connection pooling implementations.
以下示例展示了 DBCP 配置:
The following example shows DBCP configuration:
-
Java
-
Kotlin
-
Xml
@Bean(destroyMethod = "close")
BasicDataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
@Bean(destroyMethod = "close")
fun dataSource() = BasicDataSource().apply {
driverClassName = "org.hsqldb.jdbcDriver"
url = "jdbc:hsqldb:hsql://localhost:"
username = "sa"
password = ""
}
<bean id="dataSource" class="org.apache.commons.dbcp2.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 配置:
The following example shows C3P0 configuration:
-
Java
-
Kotlin
-
Xml
@Bean(destroyMethod = "close")
ComboPooledDataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("org.hsqldb.jdbcDriver");
dataSource.setJdbcUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUser("sa");
dataSource.setPassword("");
return dataSource;
}
@Bean(destroyMethod = "close")
fun dataSource() = ComboPooledDataSource().apply {
driverClass = "org.hsqldb.jdbcDriver"
jdbcUrl = "jdbc:hsqldb:hsql://localhost:"
user = "sa"
password = ""
}
<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"/>
Using DataSourceUtils
DataSourceUtils
类是一个方便且强大的帮助程序类,它提供“静态”方法来从 JNDI 获取连接并在必要时关闭连接。它支持使用 DataSourceTransactionManager
、JtaTransactionManager
和 JpaTransactionManager
的线程绑定 JDBC Connection
。
The DataSourceUtils
class is a convenient and powerful helper class that provides
static
methods to obtain connections from JNDI and close connections if necessary.
It supports a thread-bound JDBC Connection
with DataSourceTransactionManager
but
also with JtaTransactionManager
and JpaTransactionManager
.
请注意,JdbcTemplate
意味着 DataSourceUtils
连接访问,在每次 JDBC 操作后使用它,隐式参与正在进行的事务。
Note that JdbcTemplate
implies DataSourceUtils
connection access, using it
behind every JDBC operation, implicitly participating in an ongoing transaction.
Implementing SmartDataSource
SmartDataSource
接口应该由可以提供与关系数据库的连接的类实现。它扩展了 DataSource
接口,以允许使用它的类查询是否应该在给定操作后关闭连接。当您知道需要重用连接时,此用法很有效。
The SmartDataSource
interface should be implemented by classes that can provide a
connection to a relational database. It extends the DataSource
interface to let
classes that use it query whether the connection should be closed after a given
operation. This usage is efficient when you know that you need to reuse a connection.
Extending AbstractDataSource
AbstractDataSource
是 Spring DataSource
实现的 abstract
基类。它实现了所有 DataSource
实现通用的代码。如果您编写自己的 DataSource
实现,则应扩展 AbstractDataSource
类。
AbstractDataSource
is an abstract
base class for Spring’s DataSource
implementations. It implements code that is common to all DataSource
implementations.
You should extend the AbstractDataSource
class if you write your own DataSource
implementation.
Using SingleConnectionDataSource
SingleConnectionDataSource
类是对 SmartDataSource
接口的一个实现,它封装了一个在每次使用后不会关闭的单个 Connection
。这不支持多线程。
The SingleConnectionDataSource
class is an implementation of the SmartDataSource
interface that wraps a single Connection
that is not closed after each use.
This is not multi-threading capable.
如果任何客户端代码假设连接池中的连接(如使用持久性工具时)而调用 close
,您应将 suppressClose
属性设置为 true
。此设置会返回一个抑制关闭的代理,它封装物理连接。请注意,您不能再将它强制转换原生 Oracle Connection
或类似的对象。
If any client code calls close
on the assumption of a pooled connection (as when using
persistence tools), you should set the suppressClose
property to true
. This setting
returns a close-suppressing proxy that wraps the physical connection. Note that you can
no longer cast this to a native Oracle Connection
or a similar object.
SingleConnectionDataSource
主要是一个测试类。通常,它能够轻松地测试应用程序服务器外的代码,并与简单的 JNDI 环境结合使用。与 DriverManagerDataSource
相反,它始终重复使用相同连接,避免了物理连接的过度创建。
SingleConnectionDataSource
is primarily a test class. It typically enables easy testing
of code outside an application server, in conjunction with a simple JNDI environment.
In contrast to DriverManagerDataSource
, it reuses the same connection all the time,
avoiding excessive creation of physical connections.
Using DriverManagerDataSource
DriverManagerDataSource
类是对标准 DataSource
接口的一个实现,它通过 bean 属性配置一个普通的 JDBC 驱动,并每次返回一个新的 Connection
。
The DriverManagerDataSource
class is an implementation of the standard DataSource
interface that configures a plain JDBC driver through bean properties and returns a new
Connection
every time.
此实现对于 Jakarta EE 容器外的测试和单机环境很有用,它既可用作 Spring IoC 容器中的 DataSource
bean,也能与简单的 JNDI 环境结合使用。假设池中的 Connection.close()
会关闭连接,因此,任何支持 DataSource
的持久性代码都能运行。但是,使用 JavaBean 样式连接池(如 commons-dbcp
)非常容易,即使是在测试环境中,使用此类连接池通常比使用 DriverManagerDataSource
更可取。
This implementation is useful for test and stand-alone environments outside of a Jakarta EE
container, either as a DataSource
bean in a Spring IoC container or in conjunction
with a simple JNDI environment. Pool-assuming Connection.close()
calls
close the connection, so any DataSource
-aware persistence code should work. However,
using JavaBean-style connection pools (such as commons-dbcp
) is so easy, even in a test
environment, that it is almost always preferable to use such a connection pool over
DriverManagerDataSource
.
Using TransactionAwareDataSourceProxy
TransactionAwareDataSourceProxy
是一个目标 DataSource
的代理。该代理封装目标 DataSource
以添加对 Spring 管理的事务的感知。在这方面,它类似于事务性 JNDI DataSource
(由 Jakarta EE 服务器提供)。
TransactionAwareDataSourceProxy
is a proxy for a target DataSource
. The proxy wraps that
target DataSource
to add awareness of Spring-managed transactions. In this respect, it
is similar to a transactional JNDI DataSource
, as provided by a Jakarta EE server.
除了必须调用现有的代码并传递标准 JDBC |
It is rarely desirable to use this class, except when already existing code must be
called and passed a standard JDBC |
有关更多详细信息,请参阅 TransactionAwareDataSourceProxy
javadoc。
See the TransactionAwareDataSourceProxy
javadoc for more details.
Using DataSourceTransactionManager
/ JdbcTransactionManager
DataSourceTransactionManager
类是一个面向单个 JDBC DataSource
的 PlatformTransactionManager
实现。它将 JDBC Connection
从指定的 DataSource
绑定到当前正在执行的线程,这可能允许每个 DataSource
有一个线程绑定的 Connection
。
The DataSourceTransactionManager
class is a PlatformTransactionManager
implementation for a single JDBC DataSource
. It binds a JDBC Connection
from the specified DataSource
to the currently executing thread, potentially
allowing for one thread-bound Connection
per DataSource
.
应用程序代码需要通过 DataSourceUtils.getConnection(DataSource)
检索 JDBC Connection
,而不是 Java EE 的标准 DataSource.getConnection
。它抛出未签名的 org.springframework.dao
异常,而不是已签名的 SQLException
。所有框架类(如 JdbcTemplate
)都隐式使用此策略。如果不与事务管理器配合使用,则查找策略的行为与 DataSource.getConnection
完全相同,因此可以在任何情况下使用。
Application code is required to retrieve the JDBC Connection
through
DataSourceUtils.getConnection(DataSource)
instead of Java EE’s standard
DataSource.getConnection
. It throws unchecked org.springframework.dao
exceptions
instead of checked SQLExceptions
. All framework classes (such as JdbcTemplate
) use
this strategy implicitly. If not used with a transaction manager, the lookup strategy
behaves exactly like DataSource.getConnection
and can therefore be used in any case.
DataSourceTransactionManager
类支持保存点(PROPAGATION_NESTED
)、自定义隔离级别和超时,这些超时将适当地用作 JDBC 语句查询超时。为了支持后者,应用程序代码必须在为每个创建的语句使用 JdbcTemplate
或调用 DataSourceUtils.applyTransactionTimeout(..)
方法。
The DataSourceTransactionManager
class supports savepoints (PROPAGATION_NESTED
),
custom isolation levels, and timeouts that get applied as appropriate JDBC statement
query timeouts. To support the latter, application code must either use JdbcTemplate
or
call the DataSourceUtils.applyTransactionTimeout(..)
method for each created statement.
您可以使用 DataSourceTransactionManager
(而不是 JtaTransactionManager
)来处理单一资源情形,因为它不要求容器支持 JTA 事务协调器。在这些事务管理器之间切换仅是一个配置问题,前提是坚持必需的连接查找模式。请注意,JTA 不支持保存点或自定义隔离级别,并且具有不同的超时机制,但在 JDBC 资源和 JDBC 提交/回滚管理方面表现出类似的行为。
You can use DataSourceTransactionManager
instead of JtaTransactionManager
in the
single-resource case, as it does not require the container to support a JTA transaction
coordinator. Switching between these transaction managers is just a matter of configuration,
provided you stick to the required connection lookup pattern. Note that JTA does not support
savepoints or custom isolation levels and has a different timeout mechanism but otherwise
exposes similar behavior in terms of JDBC resources and JDBC commit/rollback management.
对于 JTA 风格的实际资源连接的延迟检索,Spring 为目标连接池提供了一个对应的 DataSource
代理类:请参阅 LazyConnectionDataSourceProxy
。这对于可能没有实际语句执行的潜在空事务特别有用(在这种情况下从不获取实际资源),并且也适用于希望考虑事务同步只读标志和/或隔离级别的路由 DataSource
前面(例如 IsolationLevelDataSourceRouter
)。
For JTA-style lazy retrieval of actual resource connections, Spring provides a
corresponding DataSource
proxy class for the target connection pool: see
LazyConnectionDataSourceProxy
.
This is particularly useful for potentially empty transactions without actual statement
execution (never fetching an actual resource in such a scenario), and also in front of
a routing DataSource
which means to take the transaction-synchronized read-only flag
and/or isolation level into account (e.g. IsolationLevelDataSourceRouter
).
LazyConnectionDataSourceProxy
还为只读连接池提供特殊支持,以便在只读事务期间使用,从而避免在从主连接池获取 JDBC 连接时在每个事务的开头和结尾处切换 JDBC 连接的只读标记(这可能因 JDBC 驱动而有所不同)。
LazyConnectionDataSourceProxy
also provides special support for a read-only connection
pool to use during a read-only transaction, avoiding the overhead of switching the JDBC
Connection’s read-only flag at the beginning and end of every transaction when fetching
it from the primary connection pool (which may be costly depending on the JDBC driver).
从 5.3 开始,Spring 提供了一个扩展的 |
As of 5.3, Spring provides an extended |
在异常行为方面,JdbcTransactionManager
大致等同于 JpaTransactionManager
和 R2dbcTransactionManager
,是彼此的直接伴侣/替换。另一方面,DataSourceTransactionManager
等同于 JtaTransactionManager
,并可以在其中作为直接替换。
In terms of exception behavior, JdbcTransactionManager
is roughly equivalent to
JpaTransactionManager
and also to R2dbcTransactionManager
, serving as an immediate
companion/replacement for each other. DataSourceTransactionManager
on the other hand
is equivalent to JtaTransactionManager
and can serve as a direct replacement there.