|
对于最新的稳定版本,请使用 Spring Framework 7.0.6! |
控制数据库连接
使用 DataSource
Spring 通过 DataSource 获得对数据库的连接。 DataSource 是 JDBC 规范的一部分,是一个通用的连接工厂。它可以让容器或框架将连接池和事务管理的问题隐藏在应用程序代码之外。作为开发人员,您不需要了解如何连接到数据库的细节。这是设置数据源的管理员的责任。在开发和测试代码时,您很可能会同时担任这两个角色,但您不一定需要了解生产数据源是如何配置的。
当您使用 Spring 的 JDBC 层时,可以从 JNDI 获取数据源,或者可以使用第三方提供的连接池实现进行配置。
传统选择是 Apache Commons DBCP 和 C3P0 的 bean 样式 DataSource 类;
对于现代的 JDBC 连接池,建议使用 HikariCP 及其构建器样式 API。
你应该仅在测试目的时使用 DriverManagerDataSource 和 SimpleDriverDataSource 类(如 Spring 发行版中所包含的)!这些变体不提供连接池,并且在有多个连接请求时性能较差。 |
以下部分使用了 Spring 的 DriverManagerDataSource 实现。
后面会介绍其他几种 DataSource 的变体。
要配置一个 DriverManagerDataSource:
-
以通常获取JDBC连接的方式获取一个连接,其中参数为
DriverManagerDataSource。 -
指定JDBC驱动的全限定类名,以便
DriverManager可以加载驱动类。 -
提供一个在不同JDBC驱动之间变化的URL。(请参阅您的驱动程序的文档以获取正确的值。)
-
提供一个用户名和密码以连接到数据库。
以下示例显示了如何在 Java 中配置一个 DriverManagerDataSource:
-
Java
-
Kotlin
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");
val dataSource = DriverManagerDataSource().apply {
setDriverClassName("org.hsqldb.jdbcDriver")
url = "jdbc:hsqldb:hsql://localhost:"
username = "sa"
password = ""
}
下面的示例显示了相应的 XML 配置:
<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 配置:
<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 的配置:
<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"/>
使用 DataSourceUtils
DataSourceUtils 类是一个方便且强大的帮助类,提供了
static 方法,用于从 JNDI 获取连接并在必要时关闭连接。
它支持与 Connection 的线程绑定 JDBC 连接,以及与 DataSourceTransactionManager 但
也与 JtaTransactionManager 和 JpaTransactionManager 一起使用。
请注意,JdbcTemplate 表示 DataSourceUtils 个连接访问,每次 JDBC 操作后使用它,隐式参与正在进行的事务。
实现 SmartDataSource
SmartDataSource 接口应由可以提供到关系型数据库连接的类实现。它扩展了 DataSource 接口,以让使用它的类查询在给定操作后是否应关闭连接。当你知道需要重用连接时,这种用法是高效的。
扩展 AbstractDataSource
AbstractDataSource 是 Spring 的 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 服务器提供的 DataSource 事务型 JNDI 对象。
通常不建议使用此类,除非现有的代码必须调用并传递一个标准的JDBC DataSource 接口实现。在这种情况下,您仍然可以使这段代码可用,并且同时让这段代码参与Spring管理的事务。通常更倾向于使用资源管理的高级抽象来编写您的新代码,例如 JdbcTemplate 或 DataSourceUtils。 |
查看 TransactionAwareDataSourceProxy
javadoc 以了解更多信息。
使用 DataSourceTransactionManager / JdbcTransactionManager
DataSourceTransactionManager 类是单个 JDBC PlatformTransactionManager 的 DataSource 实现。它将指定的 JDBC Connection 绑定到当前执行的线程,可能会允许每个 DataSource 有一个线程绑定的 Connection。
应用程序代码需要通过Connection到DataSourceUtils.getConnection(DataSource)来获取JDBC,而不是Java EE的标准DataSource.getConnection。它抛出未检查的org.springframework.dao异常,而不是检查的SQLExceptions。所有框架类(如JdbcTemplate)都隐式地使用此策略。如果不与事务管理器一起使用,查找策略的行为将完全像DataSource.getConnection,因此可以在任何情况下使用。
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 提交/回滚管理方面,其行为类似。
| 从5.3版本开始,Spring提供了一个扩展的<code>0</code>变体,它在提交/回滚时增加了异常转换功能(与<code>1</code>一致)。 当<code>2</code>只会抛出<code>3</code> (类似于JTA),<code>4</code>会将数据库锁定失败等转换为相应的<code>5</code>子类。请注意,应用程序代码需要准备好处理这些异常,而不仅仅期望<code>6</code>。 在这种情况下的场景中,推荐使用<code>7</code>。 |
在异常行为方面,JdbcTransactionManager大致等同于JpaTransactionManager,也等同于R2dbcTransactionManager,可以相互作为直接的伴侣/替代品。另一方面,DataSourceTransactionManager等同于JtaTransactionManager,可以在此处直接替代。