Controlling Database Connections
Using DataSource
Spring 通过 DataSource
获取与数据库的连接。DataSource
是 JDBC 规范的一部分,是一个通用的连接工厂。它允许容器或框架对应用程序代码隐藏连接池和事务管理问题。作为开发人员,您不需要了解如何连接到数据库的详细信息。这是设置数据源的管理员的职责。您很可能在开发和测试代码时扮演这两个角色,但您不必一定要知道生产数据源是如何配置的。
当您使用 Spring 的 JDBC 层时,可以从 JNDI 获取数据源,也可以使用第三方提供的连接池实现配置您自己的数据源。传统的选项是用 bean 样式的 DataSource
类的 Apache Commons DBCP 和 C3P0;对于现代 JDBC 连接池,请考虑使用构建器样式 API 的 HikariCP。
你应该只将 |
以下部分使用 Spring 的 DriverManagerDataSource
实现。稍后将涵盖其他几个 DataSource
变体。
要配置 DriverManagerDataSource
:
-
使用
DriverManagerDataSource
获取连接,如通常获取 JDBC 连接一样。 -
指定 JDBC 驱动程序的完全限定类名,以便
DriverManager
能够加载驱动程序类。 -
提供在不同 JDBC 驱动程序之间不同的 URL。(有关正确值,请参见驱动程序的文档。)
-
提供用户名和密码,以连接到数据库。
以下示例展示了如何配置 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 的基本连接性和配置。要了解有关帮助控制池特性的更多选项,请参阅各个连接池实现的产品文档。
以下示例展示了 DBCP 配置:
-
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 配置:
-
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
。
请注意,JdbcTemplate
意味着 DataSourceUtils
连接访问,在每次 JDBC 操作后使用它,隐式参与正在进行的事务。
Implementing SmartDataSource
SmartDataSource
接口应该由可以提供与关系数据库的连接的类实现。它扩展了 DataSource
接口,以允许使用它的类查询是否应该在给定操作后关闭连接。当您知道需要重用连接时,此用法很有效。
Extending AbstractDataSource
AbstractDataSource
是 Spring DataSource
实现的 abstract
基类。它实现了所有 DataSource
实现通用的代码。如果您编写自己的 DataSource
实现,则应扩展 AbstractDataSource
类。
Using SingleConnectionDataSource
SingleConnectionDataSource
类是对 SmartDataSource
接口的一个实现,它封装了一个在每次使用后不会关闭的单个 Connection
。这不支持多线程。
如果任何客户端代码假设连接池中的连接(如使用持久性工具时)而调用 close
,您应将 suppressClose
属性设置为 true
。此设置会返回一个抑制关闭的代理,它封装物理连接。请注意,您不能再将它强制转换原生 Oracle Connection
或类似的对象。
SingleConnectionDataSource
主要是一个测试类。通常,它能够轻松地测试应用程序服务器外的代码,并与简单的 JNDI 环境结合使用。与 DriverManagerDataSource
相反,它始终重复使用相同连接,避免了物理连接的过度创建。
Using DriverManagerDataSource
DriverManagerDataSource
类是对标准 DataSource
接口的一个实现,它通过 bean 属性配置一个普通的 JDBC 驱动,并每次返回一个新的 Connection
。
此实现对于 Jakarta EE 容器外的测试和单机环境很有用,它既可用作 Spring IoC 容器中的 DataSource
bean,也能与简单的 JNDI 环境结合使用。假设池中的 Connection.close()
会关闭连接,因此,任何支持 DataSource
的持久性代码都能运行。但是,使用 JavaBean 样式连接池(如 commons-dbcp
)非常容易,即使是在测试环境中,使用此类连接池通常比使用 DriverManagerDataSource
更可取。
Using TransactionAwareDataSourceProxy
TransactionAwareDataSourceProxy
是一个目标 DataSource
的代理。该代理封装目标 DataSource
以添加对 Spring 管理的事务的感知。在这方面,它类似于事务性 JNDI DataSource
(由 Jakarta EE 服务器提供)。
除了必须调用现有的代码并传递标准 JDBC |
有关更多详细信息,请参阅 TransactionAwareDataSourceProxy
javadoc。
Using DataSourceTransactionManager
/ JdbcTransactionManager
DataSourceTransactionManager
类是一个面向单个 JDBC DataSource
的 PlatformTransactionManager
实现。它将 JDBC Connection
从指定的 DataSource
绑定到当前正在执行的线程,这可能允许每个 DataSource
有一个线程绑定的 Connection
。
应用程序代码需要通过 DataSourceUtils.getConnection(DataSource)
检索 JDBC Connection
,而不是 Java EE 的标准 DataSource.getConnection
。它抛出未签名的 org.springframework.dao
异常,而不是已签名的 SQLException
。所有框架类(如 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
,并可以在其中作为直接替换。