224 lines
9.5 KiB
Plaintext
224 lines
9.5 KiB
Plaintext
[[jdbc-connections]]
|
|
= Controlling Database Connections
|
|
|
|
This section covers:
|
|
|
|
* <<jdbc-datasource>>
|
|
* <<jdbc-DataSourceUtils>>
|
|
* <<jdbc-SmartDataSource>>
|
|
* <<jdbc-AbstractDataSource>>
|
|
* <<jdbc-SingleConnectionDataSource>>
|
|
* <<jdbc-DriverManagerDataSource>>
|
|
* <<jdbc-TransactionAwareDataSourceProxy>>
|
|
* <<jdbc-DataSourceTransactionManager>>
|
|
|
|
|
|
[[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:
|
|
|
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
|
.Java
|
|
----
|
|
DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
|
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
|
|
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
|
|
dataSource.setUsername("sa");
|
|
dataSource.setPassword("");
|
|
----
|
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
|
.Kotlin
|
|
----
|
|
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 thread-bound connections with, for example, `DataSourceTransactionManager`.
|
|
|
|
|
|
[[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`
|
|
|
|
The `DataSourceTransactionManager` class is a `PlatformTransactionManager`
|
|
implementation for single JDBC data sources. It binds a JDBC connection from the
|
|
specified data source to the currently executing thread, potentially allowing for one
|
|
thread connection per data source.
|
|
|
|
Application code is required to retrieve the JDBC connection through
|
|
`DataSourceUtils.getConnection(DataSource)` instead of Jakarta 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 this transaction manager, the lookup strategy
|
|
behaves exactly like the common one. Thus, it can be used in any case.
|
|
|
|
The `DataSourceTransactionManager` class supports 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 this implementation instead of `JtaTransactionManager` in the single-resource
|
|
case, as it does not require the container to support JTA. Switching between
|
|
both is just a matter of configuration, provided you stick to the required connection lookup
|
|
pattern. JTA does not support custom isolation levels.
|
|
|
|
|
|
|