控制資料庫連線

使用 DataSource

Spring 透過 DataSource 獲取資料庫連線。DataSource 是 JDBC 規範的一部分,是一個通用的連線工廠。它允許容器或框架嚮應用程式程式碼隱藏連線池和事務管理問題。作為開發人員,您不需要知道如何連線資料庫的詳細資訊。這是設定資料來源的管理員的職責。在開發和測試程式碼時,您很可能同時扮演這兩個角色,但您不一定需要知道生產資料來源是如何配置的。

當您使用 Spring 的 JDBC 層時,可以從 JNDI 獲取資料來源,也可以透過第三方提供的連線池實現來配置自己的資料來源。傳統的選擇是 Apache Commons DBCP 和 C3P0,它們具有 bean 風格的 DataSource 類;對於現代 JDBC 連線池,可以考慮使用 HikariCP 及其構建器風格的 API。

您應該只在測試目的下使用 DriverManagerDataSourceSimpleDriverDataSource 類(Spring 分發版中包含)!這些變體不提供連線池功能,並且在對連線進行多次請求時效能不佳。

以下部分使用 Spring 的 DriverManagerDataSource 實現。其他幾種 DataSource 變體將在稍後介紹。

配置 DriverManagerDataSource

  1. 像通常獲取 JDBC 連線一樣,使用 DriverManagerDataSource 獲取連線。

  2. 指定 JDBC 驅動程式的完全限定類名,以便 DriverManager 可以載入驅動程式類。

  3. 提供一個在 JDBC 驅動程式之間有所不同的 URL。(有關正確值,請參閱您的驅動程式文件。)

  4. 提供使用者名稱和密碼以連線到資料庫。

以下示例展示瞭如何配置 DriverManagerDataSource

  • Java

  • Kotlin

  • Xml

@Bean
DriverManagerDataSource dataSource() {
	DriverManagerDataSource dataSource = new DriverManagerDataSource();
	dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
	dataSource.setUrl("jdbc:hsqldb:hsql://:");
	dataSource.setUsername("sa");
	dataSource.setPassword("");
	return dataSource;
}
@Bean
fun dataSource() = DriverManagerDataSource().apply {
	setDriverClassName("org.hsqldb.jdbcDriver")
	url = "jdbc:hsqldb:hsql://:"
	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://:");
	dataSource.setUsername("sa");
	dataSource.setPassword("");
	return dataSource;
}
@Bean(destroyMethod = "close")
fun dataSource() = BasicDataSource().apply {
	driverClassName = "org.hsqldb.jdbcDriver"
	url = "jdbc:hsqldb:hsql://:"
	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://:");
	dataSource.setUser("sa");
	dataSource.setPassword("");
	return dataSource;
}
@Bean(destroyMethod = "close")
fun dataSource() = ComboPooledDataSource().apply {
	driverClass = "org.hsqldb.jdbcDriver"
	jdbcUrl = "jdbc:hsqldb:hsql://:"
	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"/>

使用 DataSourceUtils

DataSourceUtils 類是一個方便且功能強大的幫助類,提供 static 方法以從 JNDI 獲取連線並在必要時關閉連線。它支援帶有 DataSourceTransactionManager 的執行緒繫結 JDBC Connection,也支援帶有 JtaTransactionManagerJpaTransactionManager 的執行緒繫結 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 DataSource 介面實現的現有程式碼。在這種情況下,您仍然可以使此程式碼可用,同時使此程式碼參與 Spring 管理的事務。通常,最好使用更高級別的資源管理抽象(如 JdbcTemplateDataSourceUtils)編寫自己的新程式碼。

有關更多詳細資訊,請參閱 TransactionAwareDataSourceProxy 的 javadoc。

使用 DataSourceTransactionManager / JdbcTransactionManager

DataSourceTransactionManager 類是用於單個 JDBC DataSourcePlatformTransactionManager 實現。它將指定 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 變體,它在提交/回滾時增加了異常轉換功能(與 JdbcTemplate 對齊)。DataSourceTransactionManager 只會丟擲 TransactionSystemException(類似於 JTA),而 JdbcTransactionManager 將資料庫鎖定失敗等轉換為相應的 DataAccessException 子類。請注意,應用程式程式碼需要為這些異常做好準備,而不是隻期望 TransactionSystemException。在那種情況下,JdbcTransactionManager 是推薦的選擇。

在異常行為方面,JdbcTransactionManager 大致等同於 JpaTransactionManagerR2dbcTransactionManager,彼此之間是直接的伴侶/替代品。另一方面,DataSourceTransactionManager 等同於 JtaTransactionManager,並且可以在那裡直接替代。

© . This site is unofficial and not affiliated with VMware.