控制数据库连接
使用 DataSource
Spring 通过 DataSource
获取到数据库的连接。DataSource
是 JDBC 规范的一部分,它是一个通用的连接工厂。它允许容器或框架向应用程序代码隐藏连接池和事务管理问题。作为开发人员,您不需要了解如何连接数据库的详细信息。这是设置数据源的管理员的职责。在开发和测试代码时,您很可能同时扮演这两个角色,但您不一定需要知道生产数据源是如何配置的。
当您使用 Spring 的 JDBC 层时,您可以从 JNDI 获取数据源,或者您可以使用第三方提供的连接池实现来配置您自己的数据源。传统的选择是 Apache Commons DBCP 和 C3P0,它们使用 bean 风格的 DataSource
类;对于现代 JDBC 连接池,可以考虑使用 HikariCP 及其 builder 风格的 API。
您应该只将 |
以下部分使用 Spring 的 DriverManagerDataSource
实现。其他几种 DataSource
变体将在后面介绍。
配置 DriverManagerDataSource
:
-
使用
DriverManagerDataSource
获取连接,就像您通常获取 JDBC 连接一样。 -
指定 JDBC 驱动程序的完全限定类名,以便
DriverManager
可以加载驱动程序类。 -
提供一个在 JDBC 驱动程序之间变化的 URL。(有关正确值,请参阅您的驱动程序文档。)
-
提供用户名和密码以连接到数据库。
以下示例展示了如何配置 DriverManagerDataSource
:
接下来的两个示例展示了 DBCP 和 C3P0 的基本连接和配置。要了解更多有助于控制连接池功能的选项,请参阅相应连接池实现的产品文档。
以下示例展示了 DBCP 配置:
以下示例展示了 C3P0 配置:
使用 DataSourceUtils
DataSourceUtils
类是一个方便而强大的辅助类,它提供 static
方法来从 JNDI 获取连接并在必要时关闭连接。它支持 DataSourceTransactionManager
但也支持 JtaTransactionManager
和 JpaTransactionManager
的线程绑定 JDBC Connection
。
请注意,JdbcTemplate
隐含了 DataSourceUtils
连接访问,在每个 JDBC 操作背后使用它,隐式地参与正在进行的事务。
实现 SmartDataSource
SmartDataSource
接口应由能够提供关系数据库连接的类实现。它扩展了 DataSource
接口,允许使用它的类查询给定操作后是否应关闭连接。当您知道需要重用连接时,这种用法是高效的。
扩展 AbstractDataSource
AbstractDataSource
是 Spring DataSource
实现的 abstract
基类。它实现了所有 DataSource
实现共有的代码。如果您编写自己的 DataSource
实现,则应扩展 AbstractDataSource
类。
使用 SingleConnectionDataSource
SingleConnectionDataSource
类是 SmartDataSource
接口的一个实现,它包装了一个在每次使用后不关闭的 Connection
。这不具备多线程能力。
如果任何客户端代码假定连接池调用 close
(如使用持久化工具时),您应该将 suppressClose
属性设置为 true
。此设置返回一个抑制关闭的代理,该代理包装了物理连接。请注意,您不能再将其强制转换为本机 Oracle Connection
或类似对象。
SingleConnectionDataSource
主要是一个测试类。它通常可以轻松地在应用程序服务器外部测试代码,与简单的 JNDI 环境结合使用。与 DriverManagerDataSource
不同,它始终重用相同的连接,避免过度创建物理连接。
使用 DriverManagerDataSource
DriverManagerDataSource
类是标准 DataSource
接口的一个实现,它通过 bean 属性配置一个普通的 JDBC 驱动程序,并且每次都返回一个新的 Connection
。
此实现适用于 Jakarta EE 容器之外的测试和独立环境,既可以作为 Spring IoC 容器中的 DataSource
bean,也可以与简单的 JNDI 环境结合使用。假定连接池的 Connection.close()
调用会关闭连接,因此任何 DataSource
感知的持久化代码都应该可以工作。然而,使用 JavaBean 风格的连接池(例如 commons-dbcp
)非常容易,即使在测试环境中也是如此,因此几乎总是优于使用 DriverManagerDataSource
。
使用 TransactionAwareDataSourceProxy
TransactionAwareDataSourceProxy
是目标 DataSource
的代理。该代理包装了目标 DataSource
以增加对 Spring 管理事务的感知。在这方面,它类似于 Jakarta EE 服务器提供的事务性 JNDI DataSource
。
很少需要使用此类的,除非必须调用现有代码并传入标准 JDBC |
有关更多详细信息,请参阅 TransactionAwareDataSourceProxy
javadoc。
使用 DataSourceTransactionManager
/ JdbcTransactionManager
DataSourceTransactionManager
类是单个 JDBC DataSource
的 PlatformTransactionManager
实现。它将指定 DataSource
的 JDBC Connection
绑定到当前执行的线程,可能允许每个 DataSource
一个线程绑定的 Connection
。
应用程序代码需要通过 DataSourceUtils.getConnection(DataSource)
而不是 Java EE 的标准 DataSource.getConnection
来检索 JDBC Connection
。它会抛出未检查的 org.springframework.dao
异常而不是检查的 SQLExceptions
。所有框架类(例如 JdbcTemplate
)都隐式使用此策略。如果未与事务管理器一起使用,则查找策略的行为与 DataSource.getConnection
完全相同,因此可以在任何情况下使用。
DataSourceTransactionManager
类支持保存点 (PROPAGATION_NESTED
)、自定义隔离级别和超时,这些超时将作为适当的 JDBC 语句查询超时应用。为了支持后者,应用程序代码必须使用 JdbcTemplate
或为每个创建的语句调用 DataSourceUtils.applyTransactionTimeout(..)
方法。
在单资源情况下,您可以使用 DataSourceTransactionManager
而不是 JtaTransactionManager
,因为它不需要容器支持 JTA 事务协调器。在这些事务管理器之间切换只是配置问题,前提是您坚持所需的连接查找模式。请注意,JTA 不支持保存点或自定义隔离级别,并且具有不同的超时机制,但否则在 JDBC 资源和 JDBC 提交/回滚管理方面表现出类似的行为。
对于 JTA 风格的实际资源连接的延迟检索,Spring 为目标连接池提供了相应的 DataSource
代理类:请参阅 LazyConnectionDataSourceProxy
。这对于没有实际语句执行的潜在空事务(在这种情况下永远不会获取实际资源)特别有用,并且还在路由 DataSource
之前,这意味着要考虑事务同步的只读标志和/或隔离级别(例如,IsolationLevelDataSourceRouter
)。
LazyConnectionDataSourceProxy
还为只读事务期间使用的只读连接池提供特殊支持,避免了在从主连接池获取 JDBC 连接时,在每个事务开始和结束时切换 JDBC 连接的只读标志的开销(这可能根据 JDBC 驱动程序而代价高昂)。
从 5.3 开始,Spring 提供了一个扩展的 |
在异常行为方面,JdbcTransactionManager
大致等同于 JpaTransactionManager
和 R2dbcTransactionManager
,作为彼此的直接伴侣/替代品。另一方面,DataSourceTransactionManager
等同于 JtaTransactionManager
,可以在其中直接替代。