You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
247 lines
12 KiB
247 lines
12 KiB
[[jdbc-connections]] |
|
= Controlling Database Connections |
|
|
|
This section covers: |
|
|
|
* xref:data-access/jdbc/connections.adoc#jdbc-datasource[Using `DataSource`] |
|
* xref:data-access/jdbc/connections.adoc#jdbc-DataSourceUtils[Using `DataSourceUtils`] |
|
* xref:data-access/jdbc/connections.adoc#jdbc-SmartDataSource[Implementing `SmartDataSource`] |
|
* xref:data-access/jdbc/connections.adoc#jdbc-AbstractDataSource[Extending `AbstractDataSource`] |
|
* xref:data-access/jdbc/connections.adoc#jdbc-SingleConnectionDataSource[Using `SingleConnectionDataSource`] |
|
* xref:data-access/jdbc/connections.adoc#jdbc-DriverManagerDataSource[Using `DriverManagerDataSource`] |
|
* xref:data-access/jdbc/connections.adoc#jdbc-TransactionAwareDataSourceProxy[Using `TransactionAwareDataSourceProxy`] |
|
* xref:data-access/jdbc/connections.adoc#jdbc-DataSourceTransactionManager[Using `DataSourceTransactionManager` / `JdbcTransactionManager`] |
|
|
|
|
|
[[jdbc-datasource]] |
|
== Using `DataSource` |
|
|
|
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. |
|
|
|
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. |
|
|
|
NOTE: You should use the `DriverManagerDataSource` and `SimpleDriverDataSource` classes |
|
(as included in the Spring distribution) only for testing purposes! Those variants do not |
|
provide pooling and perform poorly when multiple requests for a connection are made. |
|
|
|
The following section uses Spring's `DriverManagerDataSource` implementation. |
|
Several other `DataSource` variants are covered later. |
|
|
|
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. |
|
|
|
The following example shows how to configure a `DriverManagerDataSource` in Java: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
---- |
|
DriverManagerDataSource dataSource = new DriverManagerDataSource(); |
|
dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); |
|
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:"); |
|
dataSource.setUsername("sa"); |
|
dataSource.setPassword(""); |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
---- |
|
val dataSource = DriverManagerDataSource().apply { |
|
setDriverClassName("org.hsqldb.jdbcDriver") |
|
url = "jdbc:hsqldb:hsql://localhost:" |
|
username = "sa" |
|
password = "" |
|
} |
|
---- |
|
====== |
|
|
|
The following example shows the corresponding XML configuration: |
|
|
|
[source,xml,indent=0,subs="verbatim,quotes"] |
|
---- |
|
<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"/> |
|
---- |
|
|
|
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. |
|
|
|
The following example shows DBCP configuration: |
|
|
|
[source,xml,indent=0,subs="verbatim,quotes"] |
|
---- |
|
<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"/> |
|
---- |
|
|
|
The following example shows C3P0 configuration: |
|
|
|
[source,xml,indent=0,subs="verbatim,quotes"] |
|
---- |
|
<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"/> |
|
---- |
|
|
|
|
|
[[jdbc-DataSourceUtils]] |
|
== Using `DataSourceUtils` |
|
|
|
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`. |
|
|
|
Note that `JdbcTemplate` implies `DataSourceUtils` connection access, using it |
|
behind every JDBC operation, implicitly participating in an ongoing transaction. |
|
|
|
|
|
[[jdbc-SmartDataSource]] |
|
== Implementing `SmartDataSource` |
|
|
|
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. |
|
|
|
|
|
[[jdbc-AbstractDataSource]] |
|
== Extending `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. |
|
|
|
|
|
[[jdbc-SingleConnectionDataSource]] |
|
== Using `SingleConnectionDataSource` |
|
|
|
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. |
|
|
|
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` 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. |
|
|
|
|
|
[[jdbc-DriverManagerDataSource]] |
|
== Using `DriverManagerDataSource` |
|
|
|
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. |
|
|
|
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`. |
|
|
|
|
|
[[jdbc-TransactionAwareDataSourceProxy]] |
|
== Using `TransactionAwareDataSourceProxy` |
|
|
|
`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. |
|
|
|
NOTE: It is rarely desirable to use this class, except when already existing code must be |
|
called and passed a standard JDBC `DataSource` interface implementation. In this case, |
|
you can still have this code be usable and, at the same time, have this code |
|
participating in Spring managed transactions. It is generally preferable to write your |
|
own new code by using the higher level abstractions for resource management, such as |
|
`JdbcTemplate` or `DataSourceUtils`. |
|
|
|
See the {api-spring-framework}/jdbc/datasource/TransactionAwareDataSourceProxy.html[`TransactionAwareDataSourceProxy`] |
|
javadoc for more details. |
|
|
|
|
|
[[jdbc-DataSourceTransactionManager]] |
|
== Using `DataSourceTransactionManager` / `JdbcTransactionManager` |
|
|
|
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`. |
|
|
|
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. |
|
|
|
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. |
|
|
|
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. |
|
|
|
NOTE: As of 5.3, Spring provides an extended `JdbcTransactionManager` variant which adds |
|
exception translation capabilities on commit/rollback (aligned with `JdbcTemplate`). |
|
Where `DataSourceTransactionManager` will only ever throw `TransactionSystemException` |
|
(analogous to JTA), `JdbcTransactionManager` translates database locking failures etc to |
|
corresponding `DataAccessException` subclasses. Note that application code needs to be |
|
prepared for such exceptions, not exclusively expecting `TransactionSystemException`. |
|
In scenarios where that is the case, `JdbcTransactionManager` is the recommended choice. |
|
|
|
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. |
|
|
|
|
|
|
|
|