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.
83 lines
4.4 KiB
83 lines
4.4 KiB
[[tx-resource-synchronization]] |
|
= Synchronizing Resources with Transactions |
|
|
|
How to create different transaction managers and how they are linked to related resources |
|
that need to be synchronized to transactions (for example `DataSourceTransactionManager` |
|
to a JDBC `DataSource`, `HibernateTransactionManager` to a Hibernate `SessionFactory`, |
|
and so forth) should now be clear. This section describes how the application code |
|
(directly or indirectly, by using a persistence API such as JDBC, Hibernate, or JPA) |
|
ensures that these resources are created, reused, and cleaned up properly. The section |
|
also discusses how transaction synchronization is (optionally) triggered through the |
|
relevant `TransactionManager`. |
|
|
|
|
|
[[tx-resource-synchronization-high]] |
|
== High-level Synchronization Approach |
|
|
|
The preferred approach is to use Spring's highest-level template-based persistence |
|
integration APIs or to use native ORM APIs with transaction-aware factory beans or |
|
proxies for managing the native resource factories. These transaction-aware solutions |
|
internally handle resource creation and reuse, cleanup, optional transaction |
|
synchronization of the resources, and exception mapping. Thus, user data access code does |
|
not have to address these tasks but can focus purely on non-boilerplate |
|
persistence logic. Generally, you use the native ORM API or take a template approach |
|
for JDBC access by using the `JdbcTemplate`. These solutions are detailed in subsequent |
|
sections of this reference documentation. |
|
|
|
|
|
[[tx-resource-synchronization-low]] |
|
== Low-level Synchronization Approach |
|
|
|
Classes such as `DataSourceUtils` (for JDBC), `EntityManagerFactoryUtils` (for JPA), |
|
`SessionFactoryUtils` (for Hibernate), and so on exist at a lower level. When you want the |
|
application code to deal directly with the resource types of the native persistence APIs, |
|
you use these classes to ensure that proper Spring Framework-managed instances are obtained, |
|
transactions are (optionally) synchronized, and exceptions that occur in the process are |
|
properly mapped to a consistent API. |
|
|
|
For example, in the case of JDBC, instead of the traditional JDBC approach of calling |
|
the `getConnection()` method on the `DataSource`, you can instead use Spring's |
|
`org.springframework.jdbc.datasource.DataSourceUtils` class, as follows: |
|
|
|
[source,java,indent=0,subs="verbatim,quotes"] |
|
---- |
|
Connection conn = DataSourceUtils.getConnection(dataSource); |
|
---- |
|
|
|
If an existing transaction already has a connection synchronized (linked) to it, that |
|
instance is returned. Otherwise, the method call triggers the creation of a new |
|
connection, which is (optionally) synchronized to any existing transaction and made |
|
available for subsequent reuse in that same transaction. As mentioned earlier, any |
|
`SQLException` is wrapped in a Spring Framework `CannotGetJdbcConnectionException`, one |
|
of the Spring Framework's hierarchy of unchecked `DataAccessException` types. This approach |
|
gives you more information than can be obtained easily from the `SQLException` and |
|
ensures portability across databases and even across different persistence technologies. |
|
|
|
This approach also works without Spring transaction management (transaction |
|
synchronization is optional), so you can use it whether or not you use Spring for |
|
transaction management. |
|
|
|
Of course, once you have used Spring's JDBC support, JPA support, or Hibernate support, |
|
you generally prefer not to use `DataSourceUtils` or the other helper classes, |
|
because you are much happier working through the Spring abstraction than directly |
|
with the relevant APIs. For example, if you use the Spring `JdbcTemplate` or |
|
`jdbc.object` package to simplify your use of JDBC, correct connection retrieval occurs |
|
behind the scenes and you need not write any special code. |
|
|
|
|
|
[[tx-resource-synchronization-tadsp]] |
|
== `TransactionAwareDataSourceProxy` |
|
|
|
At the very lowest level exists the `TransactionAwareDataSourceProxy` class. This is a |
|
proxy for a target `DataSource`, which wraps the 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. |
|
|
|
You should almost never need or want to use this class, except when existing |
|
code must be called and passed a standard JDBC `DataSource` interface implementation. In |
|
that case, it is possible that this code is usable but is participating in Spring-managed |
|
transactions. You can write your new code by using the higher-level |
|
abstractions mentioned earlier. |
|
|
|
|
|
|
|
|